什么是Proxy对象
Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。
Proxy用于修改某些操作的默认行为,也可以理解为在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和改写。这个词的原理为代理,在这里可以表示由它来“代理”某些操作,译为“代理器”。
简单来说: Proxy 对象就是可以让你去对JavaScript中的一切合法对象的基本操作进行自定义。然后用你自定义的操作去覆盖其对象的基本操作。也就是当一个对象去执行一个基本操作时,其执行的过程和结果是你自定义的,而不是对象的。
Proxy的语法:
let p = new Proxy(target, handler);
Proxy对象的所有用法,都是上面的这种形式。不同的只是handle参数的写法。
其中:new Proxy用来生成Proxy实例,
target是表示所要拦截的对象,是你要代理的对象。它可以是JavaScript中的任何合法对象。如: (数组, 对象, 函数等等)
handle是用来定制拦截行为的对象(自定义操作方法的一个集合)。
p 是一个被代理后的新对象,它拥有 target 的一切属性和方法。只不过其行为和结果是在 handler 中自定义的。
var obj = new Proxy({}, {
get: function (target, propKey, receiver) {
console.log(`getting ${propKey}!`);
return Reflect.get(target, propKey, receiver);
},
set: function (target, propKey, value, receiver) {
console.log(`setting ${propKey}!`);
return Reflect.set(target, propKey, value, receiver);
}
});
举个栗子:
let obj={
a:10,
b:20,
}
const p=new Proxy(obj,{
get(target,key,value){
if(key ==='c'){
return '我是自定义的结果'
}else{
return target[key];
}
},
set(target,key,value){
if(value===4){
target[key]='我是自定义的结果';
}else{
target[key]=value;
}
}
})
console.log(obj.a) // 10
console.log(obj.c) // undefined
console.log(p.a) // 10
console.log(p.c) // 我是自定义的结果
obj.name = '李白';
console.log(obj.name); // 李白
obj.age = 4;
console.log(obj.age); // 4
p.name = '李白';
console.log(p.name); // 李白
p.age = 4;
console.log(p.age); // 我是自定义的结果
以上,构造一个代理对象时所传的第二个参数 handler,这个handler对象是有get、set两个函数方法组成的。
没代理的对象所得的结果是其JavaScript本身的执行机制运行计算后所得到的,而被代理了的对象的结果则是我们自定义的。
实际上 handler 本身就是ES6所新设计的一个对象,它的作用就是用来自定义代理对象的各种可代理操作。
下面是 Proxy 支持的拦截操作一览,一共 13 种:
- get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。
- set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。
-
has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。
// 在判断代理对象是否拥有某个属性时触发该操作,比如在执行 "foo" in proxy 时。 -
deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。
// 在删除代理对象的某个属性时触发该操作,比如在执行 delete proxy.foo 时。 - ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
- getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
- defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, 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)。
Proxy的作用
对于代理模式 Proxy 的作用主要体现在三个方面:
1、 拦截和监视外部对对象的访问
2、 降低函数或类的复杂度
2、 在复杂操作前对操作进行校验或对所需资源进行管理
网友评论