简体   繁体   English

为什么 JS 中有 Proxy «apply» 陷阱?

[英]Why is there the Proxy «apply» trap in JS?

Proxy looks like an API to extend the way we can manipulate objects such as a making single getter for all properties. Proxy看起来像 API 以扩展我们操作对象的方式,例如为所有属性制作单个 getter。 There is a Proxy trap called apply that interferes a function call.有一个名为apply的代理陷阱会干扰 function 调用。 According to the documentation, this trap can be used only with functions so this trap can be implemented with a plain old JavaScript code without Proxy:根据文档,此陷阱只能与函数一起使用,因此可以使用没有代理的普通旧 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);
};

As far as I know, the implementations above are identical (except the arguments value that isn't an array but can be easily converted to array).据我所知,上述实现是相同的(除了不是数组但可以轻松转换为数组的arguments值)。

Are the implementations really identical?实现真的相同吗? Why does the "apply" trap exist?为什么存在“应用”陷阱? What can it give compared to the plain higher order function?与普通的高阶 function 相比,它可以提供什么?

Are the implementations really identical?实现真的相同吗?

I can't see any difference between them as far as runtime behavior, other than the arguments -object difference.除了arguments差异之外,就运行时行为而言,我看不出它们之间有任何区别。 I'd personally instead do我个人会改为

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

to avoid arguments anyway.无论如何都要避免arguments

Why does the "apply" trap exist?为什么存在“应用”陷阱? What can it give compared to the plain higher order function?与普通的高阶 function 相比,它可以提供什么?

Because you might want to use the other traps at the same time.因为您可能想同时使用其他陷阱。 There's no way to create a higher-order function that is also a proxy.无法创建也是代理的高阶 function。 You could technically create a higher-order function and then wrap that with a proxy but that would get complicated quickly I imagine, and then you're splitting your trap-like behavior between a proxy handler and function-wrapping logic, where an apply trap along with all the rest keeps things cleanly associated.您可以在技术上创建一个高阶 function 然后用代理包装它,但我想这会很快变得复杂,然后您在代理处理程序和函数包装逻辑之间拆分类似陷阱的行为,其中apply陷阱连同所有的 rest 一起,让事物保持清晰的关联。

I'd also add that unless you absolutely know that you really must to use a proxy and can make your proxy behave just like the original object, which is a lot harder than you think, I'd stick with the higher-order function approach.我还要补充一点,除非您绝对知道您确实必须使用代理并且可以使您的代理的行为与原始 object 一样,这比您想象的要困难得多,否则我会坚持使用更高阶的 function 方法.

Proxy was introduced to give us object access possibilities that wasn't available before such as a single getter for any property.代理的引入为我们提供了以前不可用的 object 访问可能性,例如任何属性的单个 getter。

Personally I'd push back on this definition.我个人会反对这个定义。 Proxy was introduced to allow for JS code to implement the behavior of a JS object itself.引入Proxy是为了允许 JS 代码实现 JS object 本身的行为。 As a side-effect, that means that JS code needs to be able to intercept accesses to all properties, even if they don't exist, but I'd hesitate to call that the reason it was introduced.作为副作用,这意味着 JS 代码需要能够拦截对所有属性的访问,即使它们不存在,但我会犹豫称其为引入它的原因。 The underlying "trap"-handler approach was already defined in ECMAScript specification and JS engines already had them internally exposed to allow C++ to define how a JS object behaved, for any builtin browser APIs and things.底层的“陷阱”处理程序方法已经在 ECMAScript 规范中定义,并且 JS 引擎已经在内部公开它们以允许 C++ 定义 JS object 的行为方式,用于任何内置浏览器 API 和事物。 Proxy exposes those same hooks to JS itself to allow for JS itself to implement any API you could have otherwise only implemented in C++. Proxy向 JS 本身公开这些相同的钩子,以允许 JS 本身实现任何 API,否则您只能在 C++ 中实现。

No, they are not identical.不,它们不相同。 Your first trappedFuncton is a proxy for originalFunction , which means that it behaves exactly like originalFunction , apart from its identity and the intercepted operations (which logs arguments and drops the return value from calls, in your example).您的第一个trappedFunctonoriginalFunction的代理,这意味着它的行为与originalFunction完全一样,除了其身份和拦截操作(在您的示例中记录 arguments 并从调用中删除返回值)。

The second trappedFunction is a completely separate function object, whose only similarity to originalFunction is that it does the same thing when called.第二个trappedFunction是一个完全独立的 function object,它与originalFunction的唯一相似之处在于它在调用时执行相同的操作。 But trappedFunction.prototype.= originalFunction.prototype , and many more.但是trappedFunction.prototype.= originalFunction.prototype等等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM