proxy - handler.apply(target, object, args)方法用于拦截函数的调用
文章目录
最近因为在学ES6,除了看视频之外还阅读了网上许多优秀的文章并借鉴,谨以此文章来记录我对Proxy对象的handler.apply(target, object, args)拦截的理解及用法,proxy这部分因为篇幅较大,所以每种拦截方法我将分开写,第一次写博客,希望并感谢大神帮忙纠正。
1.什么是apply(target, object, args)?
handler.apply() 方法用于拦截函数的调用、以及call、apply和bind操作,比如proxy(…args)、proxy.call(object, …args)、proxy.apply(…),proxy.bind(…)()。
2.语法
var p = new Proxy(target, {
//target-目标对象(函数)。
//thisArg-被调用时的上下文对象。
//argumentsList-被调用时的参数数组
apply: function(target, thisArg, argumentsList) {
/*代码*/
}
});
返回值: apply方法可以返回任何值。
3.下面是两个实例和我通过上机后对其的理解
实例一
//apply(target, object, args)
//拦截函数的调用、以及call、apply和bind操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...),proxy.bind(...)()。
{
function foo(a,b){
return a+b;
}
//拦截foo函数的调用 修改foo函数实际的返回值!
let proxy=new Proxy(foo,{
apply(target, ctx, args){
// console.log(target+","+ctx,+","+args);
// console.log(ctx);
let num=1;
for(let i=0;i<args.length;i++){
// console.log(args[i]);
num*=args[i];
}
//return target(...args);
return num;
}
})
console.log('proxy',proxy(10,20));//200
let obj={
a:10,
b:30
}
//拦截foo函数的调用 修改foo函数实际的返回值!
console.log('obj-call',proxy.call(obj,10,20)); // 200 apply中的ctx为obj
console.log('obj-apply',proxy.apply(obj,[20,20,30])); // 12000 apply中的ctx为obj
console.log('window',proxy.call(window,10,20)); // 200 apply中的ctx为window
console.log(proxy.call(null,30,20)); //600 apply中的ctx为null
console.log(proxy.bind(window,20)(10)); //200 apply中的ctx为window
console.log(proxy.toString(10));//不会被拦截
}
实例2
//handler.apply() 方法用于拦截函数的调用。 handlder为对象
//实例
{
//原始函数
function sum(a,b) {
return a+b;
}
//拦截对sum的调用 可自定义修改后sum函数的返回值
let handler = {
apply(target,thisArg,argumentsList) {
// console.log(target); // f sum(a,b){return a+b;}
console.log(`Calculate sum: ${argumentsList}`);//检测函数是否被调用 是否拦截
// return target(argumentsList[0],argumentsList[1]) * 10;
return argumentsList[0] * argumentsList[1];
}
};
//实例化一个proxy对象
let proxy1 = new Proxy(sum,handler);
//通过打印结果可以看出apply()是否拦截成功
console.log('sum',sum(1,2)); //3 因为是直接调用原函数,所以没有被拦截
console.log(proxy1(1,2)); //30 通过调用proxy对象可以看出被拦截了
let obj = {
a:1,
b:3,
}
console.log('sum',sum(1,2)); //3 没有被拦截
console.log(proxy1(1,2)); //30 被拦截
//A.call(B) A.apply(B) A.bind(B)() 改变this指向,如B对象调用A对象的方法或属性,则this由A转指向B
//call
console.log('proxy-call-obj',proxy1.call(obj,10,20)); //proxy-call 200 被拦截 (被调用时的上下文对象thisArg - obj)
console.log('proxy-call-window',proxy1.call(window,10,20)); //proxy-call-window 200 被拦截 (被调用时的上下文对象thisArg - window)
console.log('proxy-call-null',proxy1.call(null,10,20)); //proxy-call-null 200 被拦截 (被调用时的上下文对象thisArg - null)
//apply
console.log('proxy-apply-obj',proxy1.apply(obj,[30,40])); //proxy-apply-obj 1200 被拦截 (被调用时的上下文对象thisArg - obj)
console.log('proxy-apply-window',proxy1.apply(window,[30,40])); //proxy-apply-window 1200 被拦截 (被调用时的上下文对象thisArg - window)
console.log('proxy-apply-null',proxy1.apply(null,[30,40])); //proxy-apply-null 1200 被拦截 (被调用时的上下文对象thisArg - null)
//bind
console.log('proxy-bind-obj',proxy1.bind(obj,4)(5)); //proxy-bind-window 20 被拦截 (被调用时的上下文对象thisArg - obj)
console.log('proxy-bind-obj',proxy1.bind(window,4)(5)); //proxy-bind-window 20 被拦截 (被调用时的上下文对象thisArg - window)
console.log('proxy-bind-null',proxy1.bind(null,4)(5)); //proxy-bind-null 20 被拦截 (被调用时的上下文对象thisArg - null)
}
注意:A.call(B), A.apply(B), A.bind(B)() 均为改变this指向,表示当B对象调用A对象的方法或属性,则this由A转指向B
总结:proxy对象实际是原始对象的代理对象,作为数据传递中间的代理层,此时handler.apply(target, object, args)的作用显著可见,即当外部想访问原始对象时,如果我们想保护原始对象返回的值,可以通过proxy代理对象拦截,并在handler.apply()方法中自行修改返回值,这就起到了保护原始对象的目的。