handler.has()
方法主要用于拦截 HasProperty
操作,即判断对象是否具有某个属性时,这个方法会生效,典型的操作就是 in
运算符。
const proxy = new Proxy(target, {has: function (target, property) {// do something},});
参数 | 说明 | 类型 |
---|---|---|
target | 目标对象 | object |
property | 需要检查是否存在的属性 | string |
该方法会拦截目标对象的以下操作:
foo in proxy
foo in Object.create(proxy)
with
检查:with(proxy){(foo);}
Reflect.has()
如果违背了以下的约束,proxy
会抛出 TypeError 异常:
以下代码演示如何拦截 in
操作符:
const proxy = new Proxy({},{has: function (target, prop) {console.log('Called:' + prop);return true;},});console.log('foo' in proxy);// "Called: foo"// true
下面代码违反了约束:
const foo = { a: 10 };Object.preventExtensions(foo);const proxy = new Proxy(foo, {has: function (target, prop) {return false;},});console.log('a' in proxy);// Uncaught TypeError: 'has' on proxy: trap returned falsish for property 'a' but the proxy target is not extensible
const handler = {has(target, prop) {if (key[0] === '_') {return false;}return key in target;},};const target = { _prop: 'foo', prop: 'foo' };const proxy = new Proxy(target, handler);console.log('_prop' in proxy);// false
上面代码中,如果原对象的属性名的第一个字符是下划线,proxy.has
就会返回 false
,从而不会被 in
运算符发现。
值得注意的是,has
方法拦截的是 HasProperty
操作,而不是 HasOwnProperty
操作,即 has
方法不判断一个属性是对象自身的属性,还是继承的属性。
另外,虽然 for...in
循环也用到了 in
运算符,但是 has
拦截对 for...in
循环不生效。