代理是目标对象的抽象。
- 目前理解为,代理就是给目标对象绑定一个指针。或者是JavaScript中的代理的原型绑定到了目标对象的原型上,但是代理的原型是undefined。
- 当对象改变或者代理改变,两者都会互相改变。一种响应式的行为。
- 可撤销代理bug: 代理变量名必须为proxy,撤销方法变量名必须为revoke
const target = {
id: 'target'
};
const handler = {};
定义一个普通的proxy代理, 为了不与可撤销代理的指定变量名冲突,普通代理尽量不要用proxy命名
const proxyObj = new Proxy(target, handler);
id属性会访问同一个值
console.log('target: ', target.id, '\n', 'proxyObj: ', proxyObj.id);
- 给目标属性赋值会反映在两个对象上
- 因为两个对象访问的是同一个值。 准确的来说,应该是访问同一个内存地址
target.id = 'target modify';
console.log('target: ', target.id, '\n', 'proxyObj: ', proxyObj.id);
- 相反的,给代理属性赋值也会反映在两个对象上
- 因为这个赋值会转移到目标对象
proxyObj.id = 'proxy modify';
console.log('target: ', target.id, '\n', 'proxyObj: ', proxyObj.id);
- hasOwnProperty() 方法在两个地方都会应用到目标对象
console.log('target hasOwnProperty: ', target.hasOwnProperty('id'));
console.log('proxyObj hasOwnProperty: ', proxyObj.hasOwnProperty('id'));
- Proxy.prototype是undefined
- 因此不能使用instanceof操作符
console.log( target instanceof Proxy); // TypeError: Function has non-object prototype 'undefined' in instanceof check
console.log(proxy instanceof Proxy); // TypeError: Function has non-object prototype 'undefined' in instanceof check
- 严格相等可以用来区分代理和目标
console.log('target equals proxy: ', target === proxyObj); // false
- 可撤销代理bug: 代理变量名必须为proxy,撤销方法变量名必须为revoke
- 可撤销代理创建
const targetObj = {
name: 'dabing'
}
const handlerObj = {
get() {
return 'intercepted';
}
}
- 定义其可撤销代理时,对应的两个变量名,必须为proxy与 revoke
const { proxy, revoke } = Proxy.revocable(targetObj, handlerObj);
console.log('targetObj : ', targetObj.name);
console.log('proxyObj : ', proxy.name);
revoke(); //撤销代理, 此操作是不可逆的。
console.log('proxyObj : ', proxy.name); // proxy引用不到目标对象,所以会报TypeError
- 代理另一个代理
const target2 = {
name: 'target object'
};
const firstProxy = new Proxy(target2, {
get() {
console.log('first Proxy');
return Reflect.get(...arguments);
}
});
const secondProxy = new Proxy(firstProxy, {
get() {
console.log('second Proxy');
return Reflect.get(...arguments);
}
});
console.log("************************************************************");
// console.log(target2.name);
// console.log(firstProxy.name);
console.log(secondProxy.name);