我正在阅读javascript the good parts,作者给出了一个类似的例子:
['d','c','b','a'].sort(function(a,b) {
return a.localeCompare(b);
});
其行为符合预期。 现在我试图做这样的事情 - 这是下一个合乎逻辑的步骤:
['d','c','b','a'].sort(String.prototype.localeCompare.call);
然后失败并出现错误:
TypeError: object is not a function
现在我想知道为什么...... 有什么想法吗?
答案 0 :(得分:4)
call
需要绑定到localeCompare
:
['d','c','b','a'].sort(Function.prototype.call.bind(String.prototype.localeCompare));
您遇到问题的原因是您传递的是sort
Function.prototype.call
。如您所知,当没有提供this
时,它将是全局对象(浏览器环境中的window
)。因此,当sort
尝试调用传递给它的函数时,它将调用call
并将this
设置为全局对象,在大多数(所有?)情况下它不是函数。因此,您必须绑定call
,以便this
始终为localeCompare
。
答案 1 :(得分:1)
您正在传递对call
函数的引用,而不保留与您打算调用它的localeCompare
方法的任何关系。因此sort
将调用String.prototype.localeCompare.call
引用的函数,但它将在全局上下文中调用它,而不是某个函数对象的方法。
正如@icktoofay指出的那样,您需要将call
函数绑定到localeCompare
。以下是一个非常简单的演示,说明如何在没有bind
方法的情况下完成此操作:
function simpleBind(fn, _this) {
return function() {
return fn.apply(_this, arguments);
}
}
['d','c','b','a'].sort(simpleBind(Function.prototype.call,
String.prototype.localeCompare));
答案 2 :(得分:1)
它不起作用的原因是String.prototype.localeCompare.call
会将Function.prototype.call
的引用返回给String.prototype.localeCompare
,而不是{{1}}。
答案 3 :(得分:0)
好的,解决了! 这就是诀窍:
['d','x','z','a'].sort(String.prototype.localeCompare.call.bind(String.prototype.localeCompare))
因为当您考虑它时,sort函数实际上调用apply on call,因此它需要绑定到字符串对象才能在范围内执行。 ^ _ ^