文章目录
- 简单说明
- 方法
- handler对象的方法
-
- handler.getPrototypeOf(target)
- handler.setPrototypeOf(target, prototype)
- handler.isExtensible(target)
- handler.preventExtensions(target)
- handler.getOwnPropertyDescriptor(target, prop)
- handler.defineProperty(target, property, descriptor)
- handler.get(target, property, receiver)
- handler.set(target, property, value, receiver)
- handler.has(target, prop)
- handler.deleteProperty(target, property)
- handler.ownKeys(target)
- handler.apply(target, thisArg, argumentsList)
- handler.construct(target, argumentsList, newTarget)
- 例子说明
简单说明
Proxy对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)。是一个用来代理基本操作的对象。可以利用它来过滤和改写用户的某些操作。
let p = new Proxy(target, handler);
target:用proxy包装的目标对象(可以是任何类型的对象,包括原生数组、函数,甚至是另一个代理。)
handler:一个对象,其属性是当执行一个操作时定义代理的行为的函数。
方法
Proxy.revocable(target, handler)
创建一个可撤销的Proxy对象。返回一个包含了所生成代理对象本身以及该代理对象的撤销方法的对象。
Proxy.revocable(target, handler);
示例说明
var revo = Proxy.revocable({},{
get(target, name){
return "\"" + name + "\"";
}
});
console.log(revo);
//Output: {proxy: Proxy, revoke: ƒ}
返回值是一个对象,结构为{proxy: Proxy, revoke: revoke}
,其中
proxy:新生成的代理对象本身,和用一般方式创建的代理对象没有什么不同,只是可被撤销。
revoke:撤销方法,调用时不需要加任何参数,就可以撤销掉和它一起生成的那个代理对象。
一旦某个代理对象被撤销,它将变的几乎完全不可用,在它身上执行任何的可代理操作都会抛出TypeError,除可代理操作其他的操作不会抛出异常。代理对象一旦被撤销,这个代理对象永远不可能恢复到原来的状态,同时和它关联的目标对象以及处理器对象将有可能被垃圾回收掉。调用撤销方法多次将不会有任何效果,也不会报错。
var proxy = revo.proxy;
proxy.a;
//result: ""a""
revo.revoke();
//撤销proxy
proxy.a;
//result: Uncaught TypeError: Cannot perform 'get' on a proxy that has been revoked
proxy.a = 1;
//result: Uncaught TypeError: Cannot perform 'set' on a proxy that has been revoked
delete proxy.a;
//result: Uncaught TypeError: Cannot perform 'deleteProperty' on a proxy that has been revoked
typeof proxy;
//result: "object"
//因为typeof不属于代理操作
代理操作:就是handler对象的方法,详细见后续,包括getPrototypeOf()、setPrototypeOf()、isExtensible(),preventExtensions()、getOwnPropertyDescriptor()、defineProperty()、has()、get()、set()、deleteProperty()、ownKeys()、apply()、construct()
handler对象的方法
handler对象是一个占位符对象,包含Proxy的捕获器,也就是代理的方法。
handler.getPrototypeOf(target)
读取代理对象的原型时调用。当其被调用时,this指向的是它所属的处理器对象。其返回值必须是一个对象或者null
target:被代理的目标对象
触发运行
- Object.getPrototypeOf()
- Reflect.getPrototypeOf()
__proto__
- Object.prototype.isPrototypeOf()
- instanceof
异常
以下情况会抛出TypeError异常
- getPrototypeOf()方法返回的不是对象也不是null
- 目标对象是不可扩展的,且getPrototypeOf()方法返回的原型不是目标对象本身的原型。
handler.setPrototypeOf(target, prototype)
主要用来拦截Oject.setPrototypeOf()。
若成功修改了[[Prototype]],setPrototypeOf方法返回true,否则返回false
var p = new Proxy(target, {
setPrototypeOf: function(target, prototype){}
}
target:被拦截的目标对象
prototype:对象新原型或为null
触发运行
- Object.setPrototypeOf()
- Reflect.setPrototypeOf()
异常
若target不可扩展,原型参数必须与Object.getPrototypeOf(target)的值相同。
handler.isExtensible(target)
判断一个代理对象是否是可扩展时触发。必须返回一个Boolean值或可转换成Boolean的值。
var p = new Proxy(target,{
isExtensible(target){
}
});
target:目标对象
其this绑定在handler对象上。
触发运行
- Object.isExtensible()
- Reflect.isExtensible()
异常
- Object.isExtensible(proxy)必须同Object.isExtensible(target)返回相同值。也就是必须返回true或为true的值,返回false和false的值都会抛出TypeError错误,表示不可扩展。
handler.preventExtensions(target)
用于设置对Object.preventExtensions()的拦截。返回一个布尔值
var p = new Proxy(target, {
preventExtensions: function(target){
}
});
target:所要拦截的目标对象
触发运行
- Object.preventExtensions()
- Reflect.preventExtensions()
异常
违反以下情况抛出TypeError
- 若Object.isExtensible(proxy)是false,则Object.preventExtensions(proxy)只能返回true
handler.getOwnPropertyDescriptor(target, prop)
在获取代理对象某个属性的属性描述是触发该操作。返回一个object或undefined
var p = new Proxy(target,{
getOwnPropertyDescriptot(target, prop){}
})
target:目标对象
prop:所返回的属性的名称