Proxy了解
Proxy用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种'元编程',即对编程语言进行编程.
Proxy可以理解成,在目标对象之前假设一层拦截,外界对该对象的访问,都必须先通过这层拦截,一次提供了一种机制,可以对外界的访问进行过滤和改写.Proxy这个词的原意是代理,用在这里表示由它来'代理'某些操作,可以译为'代理器'.
Proxy对象的常用解构组成:
let proxy=new Proxy(target,handler);
>>target:表示需要被代理的目标对象
>>handler:也是一个对象,对象中分别存在两个属性方法:get和set
>>>> get属性方法用于拦截某个属性的读取操作
>>>> set属性方法用于拦截某个属性的设置操作
handler:{
get(target,_prop,_proxy){
// target:表示被代理的对象
// _prop:表示读取的被代理对象的属性
// _proxy:可选参数,表示Proxy实例对象
},
set(target,_prop,_value,_proxy){
// target:表示被代理的对象
// _prop:表示设置的被代理的对象的属性
// _value:表示设置的值
// _proxy:可选参数,表示Proxy实例对象
}
}
注意:
要使得
Proxy
起作用,必须针对Proxy
实例对象进行操作,而不是针对目标对象(被代理对象)进行操作。
简单案例:
/** 对象代理 **/
// 创建一个对象person(被代理的对象)
const person={
name:'XiaoMei',
age:29,
sex:'女',
address:"江苏南京"
}
// 创建一个Proxy实例对象代理person
const proxyPerson=new Proxy(person,{
get(target,_prop){
// 设置需要获取年龄时,一律返回18
return _prop==='age'?18:target[_props];
},
set(target,_prop,_value){
// 当设置address属性,且属性值中含有 '北京' 字符时,该属性保持不变
if(_prop==='address'&&_value.indexOf('北京')!=-1){
return;
}
return (target[_prop] = _value);
}
})
proxyPerson.address='福建厦门';
console.log(person); // {name:'XiaoMei',age:30,sex:'女',address:'福建厦门'};
proxyperson.address='中国北京';
console.log(person); // {name:'XiaoMei',age:30,sex:'女',address:'江苏南京'};
console.log(proxyPerson.age); // 18
console.log(proxyPerson.name); // XiaoMei
/** 数组代理 **/
const list=['Hello',true,2020];
const listProxy=new Proxy(list,{
get(target,_prop){
return _prop>target.length-1?'暂无数据':target[_prop];
},
set(target,_prop,_value){
if(target.includes(_value)){
console.log('数据已经存在');
return;
}
console.log('插入成功')
return target.push(_value);
}
})
console.log(listProxy[3]); // 暂无数据
console.log(listProxy[2]); // 2020
listProxy[listProXy.length]=1; // 插入成功
listProxy[listProxy.length]='Hello';
Proxy支持拦截的操作
get(target, _prop, _proxy):
拦截被代理对象属性的读取,比如
proxy.foo
和proxy['foo']
。set(target, _prop, _value,_proxy):
拦截对象属性的设置,比如
proxy.foo = v
或proxy['foo'] = v
,返回一个布尔值。has(target, _prop):
拦截 _prop in proxy`的操作(即拦截判断指定属性是否属于指定对象的操作),返回一个布尔值。
deleteProperty(target, _prop):
拦截
delete proxy[_prop]
的操作,返回一个布尔值。ownKeys(target):
拦截
Object.getOwnPropertyNames(proxy)
、Object.getOwnPropertySymbols(proxy)
、Object.keys(proxy)
、for...in
循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()
的返回结果仅包括目标对象自身的可遍历属性。getOwnPropertyDescriptor(target, _prop):
拦截
Object.getOwnPropertyDescriptor(proxy, _prop)
,返回属性的描述对象。defineProperty(target, _prop, propDesc):
拦截
Object.defineProperty(proxy, _prop, propDesc)
、Object.defineProperties(proxy, propDescs)
,返回一个布尔值。preventExtensions(target):
拦截
Object.preventExtensions(proxy)
,返回一个布尔值。getPrototypeOf(target):
拦截
Object.getPrototypeOf(proxy)
,返回一个对象。isExtensible(target):
拦截
Object.isExtensible(proxy)
,返回一个布尔值。setPrototypeOf(target, proto):
拦截
Object.setPrototypeOf(proxy, proto)
,返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。apply(target, object, args):
拦截 Proxy 实例作为函数调用的操作,比如
proxy(...args)
、proxy.call(object, ...args)
、proxy.apply(...)
。construct(target, args):
拦截 Proxy 实例作为构造函数调用的操作,比如
new proxy(...args)
。