proxy - handler.apply(target, object, args)方法用于拦截函数的调用

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()方法中自行修改返回值,这就起到了保护原始对象的目的。

参考链接:
对proxy的理解及其常见用法
hanlder.app() - JavaScript | MDN

猜你喜欢

转载自blog.csdn.net/weixin_43931898/article/details/102700942