前言
let kind = false;
const person = new Proxy({}, {
get (target, propKey, receiver) {
if (propKey === 'kind') {
return kind = !kind;
}
return Reflect.get(target, propKey, receiver)
}
});
if (person.kind && !person.kind) {
console.log('------');
}
// ------
果然成年人的世界不是非黑即白?(远离毒鸡汤)。
简单介绍
Proxy 是用于拦截对象访问的ES6特性。外界对代理实例的多数操作可在拦截器中捕获。
const proxy = new Proxy({}, {
get(target, propKey, receiver) { },
set(target, propKey, value, receiver) { },
has(target, propKey) { },
deleteProperty(target, propKey) { },
ownKeys(target) { },
getOwnPropertyDescriptor(target, propKey) { },
defineProperty(target, propKey, propDesc) { },
preventExtensions(target) { },
getPrototypeOf(target) { },
isExtensible(target) { },
setPrototypeOf(target, proto) { },
apply(target, object, args) { },
construct(target, args) { }
});
Proxy 支持拦截以上13种行为,详细的使用方法可以参考ES6入门-Proxy。
前言中的 Reflect ,可以理解为 Proxy 的『后门』,用于访问原始对象,同样支持13个方法,传参也与 Proxy 一致。
Proxy 很厉害,看起来可以混淆正常的逻辑判断。
使用技巧
问路
if(input.show) {
// input.show == true ?
} else {
// input.show == false ?
}
上面这段if判断在 input 是拦截器时会失效, show 可以在两次 get 给出不同的结果。如此可以穿透模块的逻辑分支,也就是投石问路的意思。输入端甚至可以通过捕获的内容输出一份日志。
const proxy = new Proxy({}, {
get (target, key) {
if (key === 'a') {
return 1;
}
}
});
console.log(JSON.parse(JSON.stringify(proxy))); // {}
不过,因为深拷贝时获取了代理的『快照』,拦截器在深拷贝后无法生效。不希望公开处理过程时,可以通过深拷贝解决。
isProxy
代理可以冒充成功是因为还无法区分拦截器和正常对象。不过拦截器状态需要对内部程序公开,经过拦截器的对象不需要再次包装拦截器。
const isProxy = Symbol();
const proxy = new Proxy({}, {
get (target, key) {
if (key === isProxy) {
return true;
}
return target[key];
}
});
console.log(proxy[isProxy]); // true
使用Symbol作为判断拦截器占用的 key 可以避免无意识下与被代理对象冲突。
Proxy 与 defineProperty
Proxy | defineProperty | 作用于 | 整个对象 | 某个属性 | 生效场景 | 访问属性 | 访问属性 | 修改原始对象 | 否 | 是 | IE兼容 | 12 | 9 | Proxy 不会替代 defineProperty,实际使用时按需求选择即可。 |
---|
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!