为什么必须显式调用 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
。函数调用的 this
值 varies 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.
的奖励
我有一个字符串," 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
。函数调用的 this
值 varies 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.
的奖励