为什么必须显式调用 JavaScript 的 `function.call`?

Why does JavaScript's `function.call` have to be called explicitly?

我有一个字符串," test "。这是一个非常丑陋的字符串,所以让我们 trim 它。

" test ".trim()returns "test"。不错!

现在让我们尝试使用该字符串作为参数。

String.prototype.trim.call(" test ") 也 returns "test"。又漂亮了!

哦,这意味着我可以使用 String.prototype.trim.call 将一组丑陋的字符串映射到 trimmed 对应物,对吧?

[" test "].map(String.prototype.trim.call) 不 return ["test"].

它抛出 TypeError: undefined is not a function

为什么不允许这样做?

所有函数call方法都是相同的函数值:

> String.prototype.trim.call === Function.prototype.call
true

> String.prototype.trim.call === alert.call
true

要调用的函数作为其 this 值传递给 Function.prototype.call。函数调用的 thisvaries depending on how the call is made:

f();             // calls f with this === undefined
x.f();           // calls x.f with this === x
x['f']();        // same as previous
f.call(y);       // calls f with this === y
f.apply(y, []);  // same as previous

在所有 不是 调用的情况下引用函数时,不涉及 this 值。

const f = x.f;   // no association with x is maintained
x();             // calls f with this === undefined

因此,当您将 String.prototype.trim.call 传递给 Array#map 时,您传递的是函数 Function.prototype.call,与 String.prototype.trim 无关。 Array#map 然后用 thisArg given as the second argument 调用它(undefined,因为你只传递了一个参数)。 Function.prototype.call 调用了给定的 this 值,因为它无法调用 undefined.

代码可以通过将 this 的正确值传递为 thisArg:

来修复
["  test "].map(String.prototype.trim.call, String.prototype.trim)

很冗长,是吧?你可以滥用原型中的所有方法都相等的事实来缩短它(Set 是一个短名称的内置函数):

["  test "].map(Set.call, ''.trim)

但即使这样也不比通常的可读方式短:

["  test "].map(x => x.trim())

没有 forwarding unexpected arguments.

的奖励