Apply函数
apply方法拦截函数的调用、call和apply操作。
apply方法可以接受三个参数,分别是目标对象、目标对象的上下文对象(this)和目标对象的参数数组
var twice = {
apply (target, ctx, args) {
console.log('target',target,'ctx',ctx,'args',args);
return Reflect.apply(...arguments) * 2;
},
};
function sum (left, right) {
return left + right;
};
var proxy = new Proxy(sum, twice);
console.log(proxy);
console.log(proxy(1, 2)) // 6
console.log(proxy.call(null, 5, 6)) // 22
console.log(proxy.apply(null, [7, 8]))// 30
Has函数
has方法用来拦截HasProperty操作,即判断对象是否具有某个属性时,这个方法会生效。典型的操作就是in运算符。
如果原对象不可配置或者禁止扩展,这时has拦截会报错。
has方法拦截的是HasProperty操作,而不是HasOwnProperty操作,即has方法不判断一个属性是对象自身的属性,还是继承的属性。另外,虽然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)
console.log('score' in oproxy2)
for (let a in oproxy1) {
console.log(oproxy1[a]);
}
for (let b in oproxy2) {
console.log(oproxy2[b]);
}
}
construct方法
用于拦截new命令,下面是拦截对象的写法。
construct方法可以接受两个参数。
target: 目标对象
args:构建函数的参数对象
construct方法返回的必须是一个对象,否则会报错。
var p = new Proxy(function () {}, {
construct: function(target, args) {
console.log('called: ' + args.join(', '));
return { value: args[0] * 10 };
}
});
console.log((new p(1)).value)
deleteProperty()
deleteProperty方法用于拦截delete操作,如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除。
目标对象自身的不可配置(configurable)的属性,不能被deleteProperty方法删除,否则报错
let handler = {
deleteProperty (target, key) {
if(invariant(key, 'delete')){
// delete target[key];
return true
}else{
return false
}
}
};
function invariant (key, action) {
if (key[0] === 'p') {
throw new Error(`Invalid attempt to ${action} private "${key}" property`);
}else{
return true;
}
}
let target = { _prop: 'foo',prop:'foo' };
let proxy = new Proxy(target, handler);
console.log(delete proxy._prop);
console.log(proxy);
}