2011-12-11 32 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

calllocaleCompareにバインドする必要があります

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

あなたが問題を抱えている理由は、あなたがsortFunction.prototype.callを渡しているということです。ご存じのとおり、thisが提供されていない場合は、グローバルオブジェクト(ブラウザ環境ではwindow)になります。したがって、sortが渡された関数を呼び出そうとすると、thisがグローバルオブジェクトに設定されたcallが呼び出されます。ほとんどの(すべての)ケースは関数ではありません。したがって、callをバインドする必要がありますので、thisは常にlocaleCompareです。

+1

@RightSaidFred:それは何をすべきかです。 .localeCompare( "a"、 "b") ';のような' 'localeCompare''を使用しないでください。 .localeCompare( "b") 'のように使用します。 – icktoofay

+1

あなたは絶対に正しいです。 +1 – RightSaidFred

+0

こんにちは!ありがとう、私も解決策を見つけたとアイデアを持っていたが、それは速かったwhoosh: 私はこの場所は、言語の共有の関心のためだけに多くの質問が必要だと思う... –

1

localeCompareメソッドとの関係を維持しないで、call関数への参照を渡しています。したがって、sortString.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)) 

原因: これは、トリックを行います。 ^ _^

関連する問題