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

时间:2018-07-30 00:40:26

标签: javascript prototype method-call

我有一个字符串," test "。这是一个非常丑陋的字符串,所以让我们对其进行修剪。

" test ".trim()返回"test"。很好!

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

String.prototype.trim.call(" test ")也返回"test"。再次好!

哦,这意味着我可以使用String.prototype.trim.call来通过它们对应的修剪字符串映射一个难看的字符串数组,对吧?

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

它抛出TypeError: undefined is not a function

为什么不允许这样做?

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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