为什么 JS 中有代理"应用"陷阱?



代理看起来像一个API,它扩展了我们可以操作对象的方式,例如为所有属性创建单个getter。有一个名为apply的代理陷阱会干扰函数调用。根据文档,这个陷阱只能与函数一起使用,所以这个陷阱可以用一个没有代理的普通旧JavaScript代码来实现:

// Proxy method
const trappedFunction = new Proxy(originalFunction, {
apply: function(target, thisArg, argumentsList) {
console.log(thisArg, argumentsList);
return target.apply(thisArg, argumentsList);
}
});
// Higher order function method
var trappedFunction = function () {
console.log(this, arguments);
return originalFunction.apply(this, arguments);
};

据我所知,上面的实现是相同的(除了参数值不是数组,但可以很容易地转换为数组(。

这些实现真的相同吗?为什么存在"应用"陷阱?与普通的高阶函数相比,它能给出什么?

实现真的相同吗?

就运行时行为而言,我看不出它们之间有任何区别,除了arguments-对象的区别。我个人会做

var trappedFunction = function (...args) {
console.log(this, args);
originalFunction.apply(this, args);
};

无论如何都要避免CCD_ 2。

为什么存在"应用"陷阱?与普通的高阶函数相比,它能给出什么?

因为您可能希望同时使用其他陷阱。没有办法创建一个也是代理的高阶函数。从技术上讲,你可以创建一个更高阶的函数,然后用代理来包装它,但我想这会很快变得复杂,然后你在代理处理程序和函数包装逻辑之间划分类似陷阱的行为,其中apply陷阱和所有其他陷阱保持了干净的关联。

我还想补充一点,除非你绝对知道你真的必须才能使用代理,并且可以让你的代理表现得像原始对象一样,这比你想象的要困难得多,否则我会坚持高阶函数的方法。

Proxy的引入为我们提供了以前不可用的对象访问可能性,例如任何属性的单个getter。

就我个人而言,我会反驳这个定义。引入Proxy是为了允许JS代码实现JS对象本身的行为。作为一个副作用,这意味着JS代码需要能够拦截对所有属性的访问,即使它们不存在,但我不愿意称之为引入它的原因。ECMAScript规范中已经定义了底层的"陷阱"处理程序方法,JS引擎已经在内部公开了它们,以允许C++为任何内置浏览器API和其他东西定义JS对象的行为。Proxy将这些相同的挂钩暴露给JS本身,以允许JS本身实现任何API,否则您只能在C++中实现。

不,它们不完全相同。您的第一个trappedFunctonoriginalFunction的代理,这意味着它的行为与originalFunction完全相同,除了它的标识和截获的操作(在您的示例中,它记录参数并删除调用的返回值(。

第二个trappedFunction是一个完全独立的函数对象,它与originalFunction的唯一相似之处在于,它在调用时做相同的事情。但是trappedFunction.prototype != originalFunction.prototype,还有更多。

最新更新