介绍
has方法用来拦截hasProperty操作,即判断对象是否具有某个属性时,这个方法会生效。
典型的操作就是in运算符。
has方法可以接受两个参数,分别是目标对象、需查询的属性名。
demo1 下面的例子使用has方法隐藏某些属性,不被in运算符发现。
{
var handler = {
has (target,key) {
if(key[0] === "_") {
return false;
}
return key in target;
}
};
var target = {_prop:'foo',prop:'foo'};
var proxy = new Proxy(target,handler);
console.log("_prop" in proxy);
console.log("prop" in proxy);
}
//上面代码中,如果原对象的属性名的第一个字符是下划线,proxy.has就会返回false,从而不会被in运算符发现。
//注意,如果原对象不可配置或者禁止扩展,这时has拦截会报错。
demo2
{
var obj = {a:10};
Object.preventExtensions(obj);
//Object.preventExtensions:阻止对象扩展,让一个对象变的不可扩展,也就是永远不能再添加新的属性
var p = new Proxy(obj,{
has:function(target,prop) {
return false
}
});
// console.log("a" in p);
//Uncaught TypeError: 'has' on proxy: trap returned falsish for property 'a' but the proxy target is not extensible
}
//上面的代码中,obj对象禁止扩展,结果使用has拦截就会报错。也就是说,如果某个属性不可配置(或者目标对象不可扩展),
//则has方法就不得“隐藏”(即返回false)目标对象的该属性。
//注意,has方法拦截的是hasProperty操作,而不是HasOwnProperty操作,
//即has方法不判断一个属性是对象自身的属性,还是继承的属性。
demo3 虽然for…in 循环也用到了in运算符,但是has拦截对for…in循环不生效。
{
let stu1 = {name:'张三',score:59};
let stu2 = {name:'李四',score:99};
let handler = {
has(target,prop) {
if(prop === 'score' && target[prop]<60) {
console.log(`${target.name}不及格`);
return false;
}
return prop in target;
}
};
let oproxy1 = new Proxy(stu1,handler);
let oproxy2 = new Proxy(stu2,handler);
console.log("score" in oproxy1); //false
console.log("score" in oproxy2);//true
for(let a in oproxy1) {
console.log(oproxy1[a]);//张三 59
}
for(let b in oproxy2) {
console.log(oproxy2[b]);//李四 99
}
}
//上面代码中,has拦截只对in运算符生效,对for...in循环不生效,导致不符合要求的属性没有被for...in循环所排除。