元のソース: http://twitter.com/tobeytailor/status/8998006366
(x=[].reverse)() === window // true
この動作がすべてのネイティブ型に影響することに気付きました。ここで正確に何が起こっているのですか?
元のソース: http://twitter.com/tobeytailor/status/8998006366
(x=[].reverse)() === window // true
この動作がすべてのネイティブ型に影響することに気付きました。ここで正確に何が起こっているのですか?
this
これは、JavaScriptでバインディングが機能する奇妙な方法と関係があります。
[].reverse
reverse
空のリストのメソッドです。あなたがそれを呼ぶならば、次の1つを通して:
[].reverse();
[]['reverse']();
([].reverse)();
this
次に、リストインスタンスにバインドされて実行されます[]
。しかし、それを切り離すと:
x= [].reverse;
x();
this
バインディングなしで実行されるためthis
、関数ではグローバル()オブジェクトを指します。これwindow
は、JavaScriptの最悪で、最も誤解を招く設計ミスの1つです。
(x=[].reverse)()
デタッチも行っています。代入演算子は渡されたものと同じ関数オブジェクトを返すため、何もしていないように見えますが、JavaScriptをバインドする限定された特殊なケースを壊すという副作用がありますthis
。
だからあなたは言っています:
Array.prototype.reverse.call(window)
reverse
は、他の多くのArray.prototype
メソッドと同様に、ECMAScriptによって定義され、ネイティブシーケンスのようなオブジェクトで機能します。数値文字列キー(最大object.length
)を使用して項目を反転し、オブジェクトを返します。したがって、プロパティを持つすべての型に渡されたオブジェクトを返しlength
ます。
window
に対応する長さプロパティがあるため、を指してwindow.frames.length
このメソッドを呼び出すと機能し、を返します。理論的には、それでも失敗する可能性があります。理由は次のとおりです。this
window
window
window
「ネイティブオブジェクト」ではなく「ホストオブジェクト」にすることができます。この場合、他のプロトタイプのメソッドに渡すことができるものに関する保証は必ずしも適用されません。とただし、現在のブラウザでは、前者の場合は機能し、後者はエラーなしでサイレントに失敗するため===window
、例外ではなく動作が発生します。