[英]Why does JavaScript's `function.call` have to be called explicitly?
I have a string, " test "
. 我有一个字符串" test "
。 It's a really ugly string, so let's trim it. 这是一个非常丑陋的字符串,所以让我们对其进行修剪。
" test ".trim()
returns "test"
. " test ".trim()
返回"test"
。 Nice! 太好了!
Now let's try to do it with that string as an argument. 现在,让我们尝试使用该字符串作为参数。
String.prototype.trim.call(" test ")
also returns "test"
. String.prototype.trim.call(" test ")
也返回"test"
。 Nice again! 再次好!
Oh, that means I can use String.prototype.trim.call
to map an array of ugly strings by their trimmed counterparts, right? 哦,这意味着我可以使用String.prototype.trim.call
来按修剪后的对应字符串映射难看的字符串数组,对吗?
[" test "].map(String.prototype.trim.call)
does not return ["test"]
. [" test "].map(String.prototype.trim.call)
不返回["test"]
。
It throws TypeError: undefined is not a function
. 它引发TypeError: undefined is not a function
。
Why is this not allowed? 为什么不允许这样做?
All function call
methods are the same function value: 所有函数call
方法都具有相同的函数值:
> String.prototype.trim.call === Function.prototype.call
true
> String.prototype.trim.call === alert.call
true
The function to be called is passed to Function.prototype.call
as its this
value. 要调用的Function.prototype.call
作为this
值传递给Function.prototype.call
。 The this
value for a function call varies depending on how the call is made : 函数调用的this
值取决于调用方式 :
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
When referencing a function in all cases that aren't calls, there is no this
value involved. 在所有非调用情况下都引用函数时, 不涉及this
值。
const f = x.f; // no association with x is maintained
x(); // calls f with this === undefined
So, when you pass String.prototype.trim.call
to Array#map
, you're passing the function Function.prototype.call
, with no relationship to String.prototype.trim
. 因此,当您将String.prototype.trim.call
传递给Array#map
,您传递的是函数Function.prototype.call
,而与String.prototype.trim
没有任何关系。 Array#map
then calls it with the thisArg
given as the second argument ( undefined
, since you only passed one argument). 然后, Array#map
使用thisArg
作为第二个参数 ( undefined
,因为您仅传递了一个参数)来调用它。 Function.prototype.call
calls the this
value it was given, as it does, and fails because it can't call undefined
. Function.prototype.call
确实会调用给定的this
值,但失败了,因为它无法调用undefined
。
The code is fixable by passing the correct value of this
as thisArg
: 通过将this
的正确值作为thisArg
传递,可以thisArg
:
[" test "].map(String.prototype.trim.call, String.prototype.trim)
Pretty verbose, huh? 很冗长,是吗? You can abuse the fact that all methods from prototypes are equal to make it shorter ( Set
being a built-in function with a short name): 您可能会滥用这样一个事实,即原型中的所有方法都等同于使它更短( Set
是一个内置函数,简称):
[" test "].map(Set.call, ''.trim)
but even that's no shorter than the usual, readable way: 但即使如此,它也不会比通常的可读方式短:
[" test "].map(x => x.trim())
which has the bonus of not forwarding unexpected arguments . 它具有不转发意外参数的好处。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.