23

元のソース: http://twitter.com/tobeytailor/status/8998006366

(x=[].reverse)() === window // true

この動作がすべてのネイティブ型に影響することに気付きました。ここで正確に何が起こっているのですか?

4

1 に答える 1

41

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このメ​​ソッドを呼び出すと機能し、を返します。理論的には、それでも失敗する可能性があります。理由は次のとおりです。thiswindowwindow

  1. window「ネイティブオブジェクト」ではなく「ホストオブジェクト」にすることができます。この場合、他のプロトタイプのメソッドに渡すことができるものに関する保証は必ずしも適用されません。と
  2. ウィンドウに実際にフレーム/iframeがある場合、それらの順序を逆にしようとしますが、フレームコレクションは読み取り専用であるため、これは機能しません。

ただし、現在のブラウザでは、前者の場合は機能し、後者はエラーなしでサイレントに失敗するため===window、例外ではなく動作が発生します。

于 2010-02-14T14:28:07.973 に答える