2011-12-11 52 views
3

我读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

call需要绑定到localeCompare

['d','c','b','a'].sort(Function.prototype.call.bind(String.prototype.localeCompare)); 

你有一个问题的原因是要传递sortFunction.prototype.call。如您所知,当没有提供this时,它将是全局对象(浏览器环境中的window)。因此,当sort试图调用传递给它的函数时,它将调用call并将this设置为全局对象,在大多数(所有?)情况下,该全局对象不是函数。因此,您必须绑定call,所以this总是localeCompare

+1

@RightSaidFred:这就是它应该做的。你不使用'localeCompare'就像''一些字符串'.localeCompare(“a”,“b”)';你使用它就像'“a”.localeCompare(“b”)'。 – icktoofay

+1

你是对的。 +1 – RightSaidFred

+0

嗨!谢谢,我找到了解决方案也得到了主意,但是,这是很快的:) 在旁边说明我认为这个地方需要更多的问题,只是为了语言的共享利益... –

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)); 
+0

谢谢,很好的绑定功能。 ;)看看这里,我真的很喜欢这里所做的:https://github.com/kriskowal/es5-shim –

1

它不工作的原因是String.prototype.localeCompare.callFunction.prototype.call返回引用不String.prototype.localeCompare像你想象的。

0

好的,解决了! 这样做的伎俩:

['d','x','z','a'].sort(String.prototype.localeCompare.call.bind(String.prototype.localeCompare)) 

因为当你去想它的排序功能实际上是调用呼叫适用,所以它需要以范围执行绑定到字符串对象。 ^ _^