ES6 Proxy apply的疑问

var twice = {
    apply (target, ctx, args) {
        return Reflect.apply(...arguments) * 2;
    }
};
function sum (left, right) {
    return left + right;
};

var proxy = new Proxy(sum, twice);
console.log(proxy(1, 2))

apply方法拦截函数的调用、call和apply操作。
想了蛮久,始终没懂执行流程。

阅读 5.1k
1 个回答

拦截器中的Reflect.apply应该相当于调用sum.bind(ctx)ctx是调用时的上下文对象,这里是undefined
这样你调用proxy(1,2)的返回值就相当于,Reflect.apply(...arguments)*2,也就是sum.bind(undefined)(1,2)

阮大大有写到:

Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

我个人理解是,本来你能直接达到目标(直接调用sum),而现在你想访问对象会经过一个拦截层,你可以在调用前修改参数,也可以在调用后修改返回值(比如本例的*2)。
拦截器类似元编程,相当于修改语言特性的语法,比如本例就是对函数的apply机制进行修改,其他代理如getset等相当于对对象的读写特性进行了修改,表面上看就好像语言特性被修改了。
看下这两个例子应该就能明白如何用Proxy来代理一个函数:

function sum(left, right) {
  return (this.x || left) + right;
}
var twice = {
  apply(target, ctx, args) {
    console.log(ctx == obj);
    return Reflect.apply(...arguments) * 2;
  },
};

var proxy = new Proxy(sum, twice);
let obj = { test: "test", proxy, x: 33 };
console.log(obj.proxy(1, 2));
//true
//70
//可见ctx为执行环境this

var twice_changeParams = {
  apply(target, ctx, args) {
    args[1] = args[1] + 5;
    return Reflect.apply(...arguments) * 2;
  },
};
proxy = new Proxy(sum, twice_changeParams);
console.log(proxy(1, 2));
// 16
//16为sum(1,(2+5))*2 分别对输入和输出进行了拦截
//这就是拦截器的含义
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题