web-dev-qa-db-ja.com

このJavaScript / jQuery構文はどのように機能しますか:(function(window、undefined){})(window)?

jQuery 1.4ソースコードを実際に見て、次のようにカプセル化されていることに気付いたことがありますか。

(function( window, undefined ) {

  //All the JQuery code here 
  ...

})(window);

JavaScript Namespacing と「 重要なペアのペア 」という別の記事を読んだので、ここで何が起こっているのかを知っています。

しかし、私はこの特定の構文を見たことがありません。それは何ですかundefinedそこで何をしていますか?そして、なぜwindowを渡し、最後に再び表示する必要があるのですか?

152
dkinzer

未定義は通常の変数であり、undefined = "new value";で簡単に変更できます。したがって、jQueryは、実際には未定義のローカル「未定義」変数を作成します。

パフォーマンス上の理由から、ウィンドウ変数はローカルになります。 JavaScriptは変数を検索するときに、変数名が見つかるまでローカル変数を最初に調べるためです。見つからない場合、JavaScriptはグローバル変数をフィルタリングするまで次のスコープなどを通過します。そのため、ウィンドウ変数をローカルにすると、JavaScriptはそれをより速く検索できます。詳細: JavaScriptの高速化-Nicholas C. Zakas

157
Vincent

未定義

undefinedを引数として宣言し、値を渡さないことにより、グローバルスコープ内の単なる上書き可能な変数であるため、常に未定義であることを保証します。これにより、a === undefinedは、数文字を節約するtypeof a == 'undefined'の安全な代替手段になります。また、undefineduに短縮して、さらにいくつかの文字を保存できるため、コードがよりミニファイヤフレンドリーになります。

ウィンドウ

windowを引数として渡すと、コピーがローカルスコープに保持され、パフォーマンスに影響します: http://jsperf.com/short-scopewindowへのすべてのアクセスは、スコープチェーンの1レベル下に移動する必要があります。 undefinedと同様に、ローカルコピーを使用すると、より積極的な縮小が可能になります。


サイドノート:

これはjQuery開発者の意図ではなかったかもしれませんが、windowを渡すと、ライブラリをサーバー側のJavascript環境により簡単に統合できます。たとえば、 node.js -ここでグローバルwindowオブジェクトはありません。このような状況では、windowオブジェクトを別の行に置き換えるために1行だけを変更する必要があります。 jQueryの場合、HTMLスクレイピングの目的でモックwindowオブジェクトを作成して渡すことができます( jsdom などのライブラリがこれを実行できます)。

53
David Tang

他はundefinedを説明しています。 undefinedは、任意の値に再定義できるグローバル変数のようなものです。この手法は、誰かがundefined = 10どこか。渡されない引数は、変数undefinedの値に関係なく、実undefinedであることが保証されます。

ウィンドウを渡す理由は、次の例で説明できます。

(function() {
   console.log(window);
   ...
   ...
   ...
   var window = 10;
})();

コンソールは何をログに記録しますか? windowオブジェクトの値は正しいですか?違う! 10?違う! undefinedを記録します。 Javascriptインタープリター(またはJITコンパイラー)は、このように書き換えます-

(function() {
   var window; //and every other var in this function

   console.log(window);
   ...
   ...
   ...
   window = 10;

})();

ただし、window変数を引数として取得する場合、varは存在しないため、驚きはありません。

JQueryがそれを行っているかどうかはわかりませんが、何らかの理由で関数内のwindowローカル変数を再定義する場合は、グローバルスコープから借用することをお勧めします。

16
Chetan Sastry

誰かがIEでウィンドウオブジェクトを再定義することにした場合に備えて、windowが渡されます。後で何らかの方法で再割り当てされた場合に備えて、undefinedにも同じと仮定します。

そのスクリプトの一番上のwindowは、引数 "window"に名前を付けています。これは、グローバルwindow参照よりもローカルな引数であり、このクロージャ内のコードが使用するものです。最後のwindowは、実際には最初の引数に渡すものを指定しています。この場合、windowの現在の意味は... windowその前に。

これは、jQueryで使用される最も典型的なケースであるプラグイン .noConflict() の処理を示すことにより、考えやすくなる可能性があります。そのため、コードの大部分では$、このスコープ外のjQuery以外の何かotherを意味する場合でも:

(function($) {
  //inside here, $ == jQuery, it was passed as the first argument
})(jQuery);
6
Nick Craver

1000000回の繰り返しでテスト済み。この種のローカライズは、パフォーマンスに影響しませんでした。 1000000回の反復で1ミリ秒でさえありません。これは単に役に立たない。

5
Semra