最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does call does not work as A sort function? - Stack Overflow

programmeradmin2浏览0评论

I'm reading javascript the good parts, and the author gives an example that goes like so:

['d','c','b','a'].sort(function(a,b) {
  return a.localeCompare(b);
});

Which behaves as expected. Now I have tried to do something like this - which is the next logical step:

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

And that fails with an error:

TypeError: object is not a function

Now I left wondering why... Any ideas?

I'm reading javascript the good parts, and the author gives an example that goes like so:

['d','c','b','a'].sort(function(a,b) {
  return a.localeCompare(b);
});

Which behaves as expected. Now I have tried to do something like this - which is the next logical step:

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

And that fails with an error:

TypeError: object is not a function

Now I left wondering why... Any ideas?

Share Improve this question asked Dec 11, 2011 at 1:20 Leon FedotovLeon Fedotov 7,8715 gold badges31 silver badges33 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 6

call needs to be bound to localeCompare:

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

The reason you are having a problem is that you are passing sort Function.prototype.call. As you may know, when no this is otherwise provided, it will be the global object (window in browser environments). Thus, when sort tries to call the function passed to it, it will be calling call with this set to the global object, which in most (all?) cases is not a function. Therefore, you must bind call so this is always localeCompare.

The reason it doesn't work is that String.prototype.localeCompare.call returns a reference to Function.prototype.call not to String.prototype.localeCompare as you might think.

You're passing a reference to the call function without retaining any relationship to the localeCompare method you intend it to be called upon. So sort will invoke the function referenced byString.prototype.localeCompare.call, but it will invoke it in the global context, not as the method of some function object.

As @icktoofay pointed out, you need to bind the call function to localeCompare. Here's a much oversimplified demonstration of how this is done without the bind method:

function simpleBind(fn, _this) {
    return function() {
        return fn.apply(_this, arguments);
    }
}

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

Ok, solved it! this does the trick:

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

Cause when you think about it the sort function actually calls apply on call so it needs to be bound to the string object in order to execute in scope. ^_^

发布评论

评论列表(0)

  1. 暂无评论