Node.js中函数Proxy的apply方法未被调用,求解决方法
问题分析与解决方案
嗨,我一眼就看出问题所在啦——你用Proxy的apply陷阱时,搞错了代理的目标类型!
核心问题:apply陷阱只对函数生效
你现在的代码里,Object.assign({}, Magic.Foo)返回的是一个普通对象(哪怕这个对象里包含函数属性),而Proxy的apply陷阱只有当代理的目标本身是函数的时候,才会在调用这个函数时被触发。普通对象根本不会触发apply陷阱,这就是为啥你的代码里那个handler从来没执行过。
修正方案
根据你的需求,有两种常见的解决思路:
1. 直接代理目标函数
如果你想拦截的是Foo.runme这个函数的调用,直接把Proxy套在这个函数上就行:
var Foo = { runme: function() { return 1; } }; var Magic = { Foo: Foo }; // 给runme函数套上Proxy Magic.Foo.runme = new Proxy(Magic.Foo.runme, { apply(target, thisArg, argumentsList) { console.log("apply陷阱被触发了!"); // 调用原函数并返回结果 return target.apply(thisArg, argumentsList); } }); // 现在调用runme就会触发陷阱啦 console.log(Magic.Foo.runme()); // 先输出"apply陷阱被触发了!",再输出1
2. 代理对象,动态拦截函数调用
如果你想代理整个Foo对象,同时自动拦截对象里所有函数的调用,可以用get陷阱来实现:
var Foo = { runme: function() { return 1; } }; var Magic = { Foo: Foo }; Magic.Foo = new Proxy(Magic.Foo, { get(target, propName) { const value = target[propName]; // 如果取到的是函数,就给它套上带apply陷阱的Proxy if (typeof value === 'function') { return new Proxy(value, { apply(targetFn, thisArg, args) { console.log(`函数${propName}被调用,参数:${args}`); return targetFn.apply(thisArg, args); } }); } // 非函数属性直接返回原 value return value; } }); // 调用runme时会触发动态生成的Proxy的apply陷阱 Magic.Foo.runme(); // 输出"函数runme被调用,参数:"和1
总结一下
记住Proxy的各个陷阱都是有触发条件的:apply专门负责拦截函数调用行为,所以必须保证代理的目标是函数本身,而不是包含函数的普通对象。这样调整后,你的代码就能正常触发apply陷阱啦!
内容的提问来源于stack exchange,提问作者Dave Stein
相关产品推荐
相关产品推荐

