比方说,我想创建一个修剪其输入的函数,我可以做到的一种方法就是简单地
x => x.trim()
另一种方法是
x => String.prototype.trim.call(x)
具有的优势在于,如果x
为.trim()
定义了替代,我仍然可以从原型中获取实现。通过扩展,如果我想在.map()
中使用相同的功能,则可以两者之一
[" foo", "bar "].map(x => x.trim())
[" foo", "bar "].map(x => String.prototype.trim.call(x));
我想做一个pointfree function。我不明白的是为什么不能使用由.call
[" foo", "bar "].map(String.prototype.trim.call);
我还尝试了.apply
,因为没有参数实际上是同一回事。
同样,在地图之外,您也不能使用函数.call
函数
> fn = String.prototype.trim.call
[Function: call]
> fn('asdf')
TypeError: fn is not a function
我的问题是
String.prototype.trim.call
返回的函数到底是做什么的?那是什么功能?.call
无效?.bind
,.apply
或.call
这样做吗?答案 0 :(得分:1)
有趣的问题!归结为Array.prototype.map的签名:
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
了解您注意到的行为的关键是可选的thisArg
-这是将提供给回调的上下文
此外,from the spec:
如果提供thisArg参数来映射,它将用作回调的this值。否则,未定义的值将用作此值。
因此,这意味着undefined
将用作回调的上下文,在本例中为String.prototype.trim.call
在这里变得有趣起来……Function.prototype.call
(String.prototype.trim.call
继承了)的正常上下文是它调用的函数,即本例中的String.prototype.trim
。 Function.prototype.call
的第一个参数提供了将要调用的函数的上下文。
在<< Array >>.map(String.prototype.trim.call)
的情况下,提供给String.prototype.trim.call
的上下文为undefined
,这意味着我们最终尝试使用来自undefined
的元素的上下文来调用String.prototype.trim
数组。全清?肯定有点思想上的转变。
我们可以通过在thisArg
中将<< Array >>.map(callback, thisArg)
作为Function.call
并将console.log([" foo", "bar "].map(Function.call, String.prototype.trim));
用作回调来利用这种行为来达到我们想要的效果:
String.prototype.trim
另一种思考方式是Function.call
为{{1}}提供上下文以生成绑定函数,然后数组的每个元素为绑定函数提供上下文。
答案 1 :(得分:1)
我不明白的是为什么不能使用由
.call
创建的未调用函数[" foo", "bar "].map(String.prototype.trim.call);
这里的问题是所有函数都从call
继承相同的Function.prototype
方法;所以以上等同于
[" foo", "bar "].map(Function.prototype.call);
要使代码正常工作,call
需要“记住”您是从String.prototype.trim
而不是其他函数获得的;但这根本不是方法调用在JavaScript中的工作方式。在像foo.bar()
这样的方法调用表达式中,foo
不仅是其bar
属性被作为函数调用的对象,它还隐式地作为{{1} } 至该功能。对于this
,String.prototype.trim.call(x)
知道调用call
的唯一原因是您使用的是方法调用语法,因此可以从String.prototype.trim
中获取它。 / p>
- 在上面,
this
返回的函数到底是做什么的?那是什么功能?
这是一个方法,它带有一个对象和零个或多个参数,并且在对一个函数进行调用时,将对该函数作为对该对象的方法进行调用,并传递这些参数。
- 为什么我尝试使用
String.prototype.trim.call
无效?
因为它尝试将.call
作为自由函数而不是方法来调用;因此call
不会收到call
自变量告诉它要调用什么函数,因此它无法完成其工作。 (它很可能会收到“默认对象”,例如this
作为其window
参数;但是我不确定某些细微之处。您可以在其中尝试this
您的测试平台,看看它能为您的环境带来什么。)
- 反正有
[" foo", "bar "].map(function () { return this; })
,.bind
或.apply
这样做吗?
是;你可以这样写:
.call
其中[" foo", "bar "].map(Function.prototype.call.bind(String.prototype.trim))
是一个函数,该函数在被调用时会在Function.prototype.call.bind(String.prototype.trim)
上调用call
。 (换句话说,String.prototype.trim
处理“记住” bind
是要作为String.prototype.trim
传递的对象。)
也就是说,我真的认为您的原始版本,
this
非常优越。如果某人重写了[" foo", "bar "].map(x => x.trim())
,您应该相信它是有充分理由的,您确实应该调用该重写,而不是强制使用继承的替代。