为什么调用不能作为排序函数?

时间:2011-12-11 01:20:42

标签: javascript v8

我正在阅读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

现在我想知道为什么...... 有什么想法吗?

4 个答案:

答案 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,因此它需要绑定到字符串对象才能在范围内执行。 ^ _ ^