需求:监听某个对象属性的操作
Object.defineProperty
进行监听某个属性是否发生了变化(同时也是 vue2中实现响应式的原理)let obj = { a: 100 };
let _value = "";
Object.defineProperty(obj, "a", {
set(value) {
_value = value;
console.log("a的值发生了改变");
},
get() {
console.log("a的值发生了访问");
return _value;
},
});
obj.a = 200;
console.log(obj.a);
Object.defineProperty
属性设计的初衷并不是监听属性的操作,我们只是用这个API实现了相关的操作(无伤大雅)今后对 某个对象的操作,均可由代理对象完成,代理对象可以监听我们想要对原对象的某个操作
以下是基本使用方法
let obj = { a: 100 };
// new Proxy(target handler),
//target: 监听的属性
//handler具体操作:实际上是一个对象
let objProxy = new Proxy(obj, {
get(target, key) {
console.log(`获取了${key}的值`);
return target[key];
},
set(target, key, newValue) {
target[key] = newValue;
console.log(`对${key}进行了更改,改成了:${newValue}`);
},
});
//修改现有属性
objProxy.a = 200;
//读取现有属性
console.log(objProxy.a);
//新增一个属性
objProxy.b = 300;
console.log(objProxy.b);
Proxy13种捕获器
handler.get() handler.set() handler.has() handler.deleteProperty
//上面对handler.get() handler.set()进行了演示
let obj = { a: 100 };
// new Proxy(target handler),
//target: 监听的属性
//handler具体操作:实际上是一个对象
let objProxy = new Proxy(obj, {
get(target, key) {
console.log(`获取了${key}的值`);
return target[key];
},
set(target, key, newValue) {
target[key] = newValue;
console.log(`对${key}进行了更改,改成了:${newValue}`);
},
//删除属性的捕获器
deleteProperty(target, key) {
console.log(`${key}被删除了`);
delete target[key];
return true;
},
//in操作符的捕捉器
has(target, key) {
return key in target;
},
});
//修改现有属性
objProxy.a = 200;
//读取现有属性
console.log(objProxy.a);
//新增一个属性
objProxy.b = 300;
console.log(objProxy.b);
//删除一个属性
delete objProxy.b;
//查看属性是否存在于对象种
console.log("b" in objProxy); //false
console.log("a" in objProxy); //true
handler.apply() handler.construct()
function foo(name) {
this.name = name;
console.log(this.name);
}
let fooProxy = new Proxy(foo, {
//第一个参数,构造函数本身
//第二个参数,传入构造函数的参数
construct(target, args) {
console.log("创建了新的对象", target.name);
//返回new之后的构造函数
return new target(...args);
},
//第一个参数函数本身
//第二个参数:执行上下文的对象
//第三个参数:传入参数的数组
apply(target, thisArg, otherArg) {
//因此我们在这里可以写一些其他的操作
//调用call,apply等等
console.log("函数被调用了");
return target(...otherArg);
},
});
//通过new操作
let foo1 = new fooProxy("zhangcheng");
console.log(foo1);
//执行函数的代理
fooProxy("zhangcheng");
Reflect是一个对象,字面意思是反射
它的作用与 Object
种的操作对象的方法很类似,但是也会又细微的差别
Object.getPrototypeOf(obj)
和 Reflect.getPrototypeOf(obj)
Object.defineProperty(obj,key,{})
和 Reflect.defineProperty(obj,key,{})
有了 Object
可以进行这些操作,那么为什么还要增加 Reflect
对象呢
let obj = {a:100}
console.log(Reflect.deleteProperty(obj,"a"))//会直接返回boolean的值,显式有没有删除成功
Reflect.defineProperty(obj,"a",{})//对属性进行设置的时候,也会返回相应的boolean,来确定是否设置成功了
Reflect对象的13种用法,与Proxy一一对应
let obj = { a: 100 };
let objProxy = new Proxy(obj, {
set(target, key, newValue, receiver) {
//先前的做法
// target[key] = newValue;
//通过Reflect的做法,有返回值
if (Reflect.set(target, key, newValue)) {
console.log("修改成功");
}
},
});
objProxy.a = 200;
receiver
就是外面的 Proxy
对象receiver
参数,改变源对象种this的指向需求:创建一个对象,对象中有属性set方法,创建该对象的Proxy对象,实现监听对象内部的操作
let obj = {
_a: 100,
set a(newValue) {
console.log(this);
this._a = newValue;
},
};
let objProxy = new Proxy(obj, {
set(target, key, newValue, receiver) {
console.log("更改成功");
Reflect.set(target, key, newValue, receiver);
},
});
/**
内部操作
1.调用obj中的set方法
2.将this._a改变
*/
obj.a = 300;
/**
内部操作
1.调用objProxy中的set方法(第一次)
2.调用obj中的set方法
3.此时的this指向的是objProxy
4.所以会再次调用objProxy中的set方法(第二次)
相当于修改a的时候监听一次,修改_a的时候监听一次
*/
objProxy.a = 200;