Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
// target: 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
// handler: 一个对象,该对象的属性值通常是函数,定义了代理各种操作时p的行为。对象上的属性名是特定且可选的,如果没有某个属性,就会保留源对象的默认行为。
const p = new Proxy(target, handler)
这些方法和Reflect的方法有明显的对应关系:
// 拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
handler.apply(target, thisArg, args)
// 拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。
handler.construct(target, args)
// 拦截对象属性的读取,比如proxy.foo和proxy['foo']。
handler.get(target, name, receiver)
// 拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。
handler.set(target, name, value, receiver)
// 拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
handler.defineProperty(target, name, desc)
// 拦截delete proxy[propKey]的操作,返回一个布尔值。
handler.deleteProperty(target, name)
// 拦截propKey in proxy的操作,返回一个布尔值。
handler.has(target, name)
// 拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
handler.ownKeys(target)
// 拦截Object.isExtensible(proxy),返回一个布尔值。
handler.isExtensible(target)
// 拦截Object.preventExtensions(proxy),返回一个布尔值。
handler.preventExtensions(target)
// 拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
handler.getOwnPropertyDescriptor(target, name)
// 拦截Object.getPrototypeOf(proxy),返回一个对象。
handler.getPrototypeOf(target)
// 拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
Reflect.setPrototypeOf(target, prototype)
let data = new Proxy(response.data, {
set(obj, key, value) {
return false
}
})
class Component {
constructor () {
this.proxy = new Proxy({
id: Math.random().toString(36).slice(-8)
})
}
get id () {
return this.proxy.id
}
}
// Validator.js
export default (obj, key, value) => {
if (Reflect.has(key) && value > 20) {
obj[key] = value
}
}
import Validator from './Validator'
let data = new Proxy(response.data, {
set: Validator
})
Proxy.revocable()方法返回一个可取消的 Proxy 实例。
Proxy.revocable()方法返回一个对象,该对象的proxy属性是Proxy实例,revoke属性是一个函数,可以取消Proxy实例。
当执行revoke函数之后,再访问Proxy实例,就会抛出一个错误。
Proxy.revocable()的一个使用场景是,目标对象不允许直接访问,必须通过代理访问,一旦访问结束,就收回代理权,不允许再次访问。
let target = {};
let handler = {};
let {proxy, revoke} = Proxy.revocable(target, handler);
proxy.foo = 123;
proxy.foo // 123
revoke();
proxy.foo // TypeError: Revoked