一、proxy
Proxy 对象用于创建一个对象的代理,用代理对象覆盖目标对象,使目标对象对用户不可见,从而实现被代理对象基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
const target = new Proxy(target, handler)
target:被代理的对象
handler :一个通常以方法作为属性的对象,对代理对象的执行某些操作时,会触发对应的方法。比如:
1、赋值:触发set;
2、取值:get;
3、in操作符:触发has;
案例1:
var target = {
name: '七鸽',
phone: 13838480813
},
handle = {
get(target, key,proxy) {
console.log(arguments.length)//3
return obj[key]
},
set(target, key, value,proxy) {
console.log(arguments.length)//4
obj[key] = value
}
};
proxy = new Proxy(target, handle);
console.log(proxy.name)//七鸽
proxy.sex = 'man'
console.log(proxy.sex);//man
1-1、当访问时会触发handel对象的get的方法,传了3个参数,
参数1是目标象target;
参数2是访问属性key;
参数3是代理对象proxy;
get方法内部的arguments如下图:
1-2、当访问时会触发handel对象的set的方法,传了4个参数,
参数1是目标象target;
参数2是设置的属性名key;
参数3是设置的属性值value;
参数4是代理对象proxy;
set方法内部的arguments如下图:
1-3、假如不通过代理对象,直接操作目标对象,handle对象的方法就不会被触发。代码如下:
var target = {
name: '七鸽',
phone: 13838480813
},
handle = {
get(obj, key) {
console.log(arguments);//不打印
return obj[key]
},
set(obj, key, value) {
console.log(arguments);//不打印
obj[key] = value
}
};
proxy = new Proxy(target, handle);
target.name='舞载';
target.sex = 'man'
console.log(proxy.sex)//man
通过以上代码证明:handled对象中的get、 set方法并不执行,。但是通过代理对象也可以访问sex属性,是因为proxy对象中保存了目标对象的引用。handled对象中的get set方法不执行,也就意味着起不了拦截的作用,如果要保证100%拦截目标对象的操作,必须让目标对象指向代理对象。代码如下:
function observer(target) {
return new Proxy(target, {
get(obj, key, proxy) {
console.log(arguments.length);//3
return obj[key];
},
set(obj, key, value, proxy) {
console.log(arguments.length);//4
obj[key] = value;
}
});
}
var target = {
name: '七鸽',
phone: 13838480813,
};
target=observer(target);
target.sex = 'man';
console.log(target.sex) //man
二、reflect
reflect是一个内置对象,它并不是一个函数,提供一些类似Object静态方法的静态方法。
var target = {
name: '七鸽',
phone: 13838480813,
};
console.log(Reflect.defineProperty(target, 'sex', { value: 'man' }));//true
console.log(Reflect.set(target, 'age',18));//true
console.log(Reflect.get(target, 'age'));//18
console.log(Reflect.getOwnPropertyDescriptor(target, 'age'));
console.log(Reflect.getPrototypeOf(target));
console.log(target);
console.log(Reflect.has(target, 'name'));//true
console.log(Reflect.ownKeys(target));// ["name", "phone", "sex", "age"]
2-1、给对象添加一个属性的方法PK:
var target = {
name: '七鸽',
phone: 13838480813,
};
target.hobby='fishing';
target['id']='5454543535';
console.log(Object.defineProperty(target, 'sex', { value: 'man' }));//返回原对象
console.log(Reflect.defineProperty(target, 'job', { value: 'study' }));//true
console.log(Reflect.set(target, 'age',18));//true
console.log(Reflect.get(target, 'hobby'));//18
console.log(target);
1、Object.defineProperty和Reflect.definePropert的异同:返回值不同,设置的属性配置项都为false;
2、Reflect.defineProperty和Reflect.set的异同:返回值都是boolean值,Reflect.set添加的属性配置项都为true。
案例:Proxy与Reflect的结合使用:
function observer(target) {
return new Proxy(target, {
get(obj, key, proxy) {
console.log(arguments.length); //3
// return obj[key];
return Reflect.get(obj,key)
},
set(obj, key, value, proxy) {
console.log(arguments.length); //4
// obj[key] = value;
console.log(Reflect.set(...arguments));//true
}
});
}
target=observer(target);
target.sex = 'man';
console.log(target.sex) //舞载