web-dev-qa-db-ja.com

JavaScriptの自己実行機能の目的は何ですか?

Javascriptでは、いつこれを使いたいですか:

(function(){
    //Bunch of code...
})();

これについて:

//Bunch of code...
390
Ej.

変数スコープについてのすべて。自己実行関数で宣言された変数は、デフォルトでは、自己実行関数内のコードでのみ使用可能です。これにより、javascriptコードの他のブロックで変数に名前を付ける方法を気にせずにコードを記述できます。

例えば:

(function(){ 
    var foo = 3; 
    alert(foo); 
})(); 

alert(foo); 

Fooが定義されていないため、これは最初に「3」を警告し、次に次の警告でエラーをスローします。

371
Ken Browning

単純です。とても普通の見た目で、ほとんど快適です。

var userName = "Sean";

console.log(name());

function name() {
  return userName;
}

しかしながら。高度な文字を基本レベルの表現に変換する非常に便利なJavaScriptライブラリをページに含めるとどうなりますか?

待って…何?

というのは。誰かが何らかのアクセント(フランス語やスペイン語の文字など)を付けた文字を入力しても、「英語」の文字だけが必要な場合はどうすればよいですか?私のプログラムのA-z?まあ...スペイン語の 'n〜'とフランス語の 'e /'文字(これらにそれぞれ2文字使用しましたが、おそらくアクセントを表す文字に精神的に跳躍することができます)、それらの文字は翻訳できます「n」と「e」の基本文字に変換します。

だから誰か素敵な人が私のサイトに含めることができる包括的な文字コンバータをそこに書いています...私はそれを含めます。

1つの問題:私の関数と同じ「名前」と呼ばれる関数が含まれています。

これは、衝突と呼ばれるものです。同じ名前で、同じscopeで宣言された2つの関数があります。これを避けたいです。

そのため、何らかの方法でコードをスコープする必要があります。

Javascriptでコードをスコープする唯一の方法は、関数でコードをラップすることです。

function main() {
  // We are now in our own sound-proofed room and the 
  // character-converter libarary's name() function can exist at the 
  // same time as ours. 

  var userName = "Sean";

  console.log(name());

  function name() {
    return userName;
  }
}

これで問題が解決するかもしれません。これですべてが囲まれ、開閉ブレース内からのみアクセスできます。

関数に関数があります...これは見た目が奇妙ですが、完全に合法です。

ただ一つの問題。コードは機能しません。 userName変数がコンソールにエコーされることはありません!

この問題は、既存のコードブロックの後に関数の呼び出しを追加することで解決できます...

function main() {
  // We are now in our own sound-proofed room and the 
  // character-converter libarary's name() function can exist at the 
  // same time as ours. 

  var userName = "Sean";

  console.log(name());

  function name() {
    return userName;
  }
}

main();

または前に!

main();

function main() {
  // We are now in our own sound-proofed room and the 
  // character-converter libarary's name() function can exist at the 
  // same time as ours. 

  var userName = "Sean";

  console.log(name());

  function name() {
    return userName;
  }
}

副次的な懸念:名前「main」がまだ使用されていない可能性は何ですか? ...とても、とてもスリムです。

もっとスコープが必要です。そして、main()関数を自動的に実行する何らかの方法。

ここで、自動実行機能(または自己実行、自己実行など)を使用します。

((){})();

構文は、罪のように扱いにくいです。ただし、動作します。

関数定義を括弧で囲み、パラメータリスト(別のセットまたは括弧!)を含めると、関数として機能しますcall

自己実行構文を使用して、コードをもう一度見てみましょう。

(function main() {
  var userName = "Sean";

    console.log(name());

    function name() {
      return userName;
    }
  }
)();

ですから、あなたが読んだほとんどのチュートリアルでは、「匿名の自己実行」という用語やそれに類するもので攻撃されます。

長年にわたる専門的な開発の後、私は強くデバッグの目的で書くすべての関数に名前を付けることを促しています。

何かがうまくいかない場合(そしてそうなる場合)、ブラウザでバックトレースをチェックします。 alwaysスタックトレースのエントリに名前がある場合、コードの問題を絞り込むのが簡単です!

非常に長い時間がかかり、それが役立つことを願っています!

78
Sean Holden

自己呼び出し(自動呼び出しとも呼ばれます)は、関数が定義された直後に実行される場合です。これはコアパターンであり、JavaScript開発の他の多くのパターンの基盤として機能します。

私はそれの大ファンです:)

  • コードを最小限に抑えます
  • 動作とプレゼンテーションの分離を強制します
  • 名前の競合を防ぐクロージャを提供します

非常に なぜあなたはその良いと言うべきですか?)

もっと---(こちら

33

名前空間。 JavaScriptのスコープは関数レベルです。

19
Christoph

暗示されたグローバルに言及している答えはどれも信じられません。

(function(){})()コンストラクトは、暗黙のグローバルに対する保護を行いません。これは、私にとってより大きな懸念です。 http://yuiblog.com/blog/2006/06/01/global-domination/ を参照してください

基本的に、関数ブロックは、定義したすべての従属「グローバル変数」がプログラムに限定されていることを確認します。暗黙のグローバルの定義に対する保護は行いません。 JSHint などは、この動作を防ぐ方法に関する推奨事項を提供できます。

より簡潔なvar App = {}構文は、同様のレベルの保護を提供し、「パブリック」ページの場合は関数ブロックにラップされる場合があります。 (このコンストラクトを使用するライブラリの実際の例については、 Ember.js または SproutCore を参照してください)

privateプロパティに関する限り、パブリックフレームワークまたはライブラリを作成している場合を除き、これらのプロパティは過大評価されていますが、それらを実装する必要がある場合は、 Douglas Crockford に良いアイデアがあります。

12
David W. Keith

パラメータがあり、「コードの束」が関数を返しますか?

var a = function(x) { return function() { document.write(x); } }(something);

閉鎖。 somethingの値は、aに割り当てられた関数によって使用されます。 somethingにはいくつかの可変値(forループ)があり、aが新しい関数を持つたびに。

7
stesch

多分スコープの分離。そのため、関数宣言内の変数が外側の名前空間を汚染しないようにします。

もちろん、JS実装の半分では、とにかくそうなります。

6
chaos

これは、自己呼び出し匿名関数がどのように役立つかを示す堅実な例です。

for( var i = 0; i < 10; i++ ) {
  setTimeout(function(){
    console.log(i)
  })
}

出力:10, 10, 10, 10, 10...

for( var i = 0; i < 10; i++ ) {
  (function(num){
    setTimeout(function(){
      console.log(num)
    })
  })(i)
}

出力:0, 1, 2, 3, 4...

5
sg.cc

私はすべての答えを読みました、非常に重要なものがここにありません、私はキスします。 2つの主な理由があります。私は、匿名関数を自己実行する必要がある理由、または「Immediately-Invoked Function Expression(IIFE) "

  1. ネームスペース管理の改善(ネームスペース汚染の回避-> JSモジュール)
  2. クロージャー(OOPから既知のプライベートクラスメンバーのシミュレーション)

最初のものは非常によく説明されています。 2番目の例については、次の例を検討してください。

var MyClosureObject = (function (){
  var MyName = 'Michael Jackson RIP';
  return {
    getMyName: function () { return MyName;},
    setMyName: function (name) { MyName = name}
  }
}());

注意1:関数をMyClosureObjectに割り当てていません。さらにその関数を呼び出した結果。最後の行の()に注意してください。

注意2: Javascriptの関数についてさらに知っておく必要があるのは、内部関数が取得することですパラメーターと変数へのアクセス関数の内部で定義されています。

いくつかの実験を試してみましょう。

MyNameを使用してgetMyNameを取得できますが、動作します:

 console.log(MyClosureObject.getMyName()); 
 // Michael Jackson RIP

次の巧妙なアプローチは機能しません。

console.log(MyClosureObject.MyName); 
// undefined

しかし、別の名前を設定して、期待される結果を得ることができます。

MyClosureObject.setMyName('George Michael RIP');
console.log(MyClosureObject.getMyName()); 
// George Michael RIP

編集:上記の例では、MyClosureObjectnewprefixなしで使用するように設計されているため、慣例により大文字にしないでください。

4
Lonely

1つの違いは、関数で宣言する変数はローカルであるため、関数を終了すると消え、他のコードの他の変数と競合しないことです。

3
Guffa

javascriptの自己呼び出し関数:

自己呼び出し式は、呼び出されることなく、自動的に呼び出されます(開始されます)。自己呼び出し式は、作成された直後に呼び出されます。これは基本的に、命名の競合を回避するため、およびカプセル化を達成するために使用されます。変数または宣言されたオブジェクトは、この関数の外部ではアクセスできません。最小化(filename.min)の問題を回避するには、常に自己実行関数を使用します。

2
Kishor Vitekar

Javascriptの関数はファーストクラスのオブジェクトなので、そのように定義することにより、C++やC#のような「クラス」を効果的に定義します。

その関数は、ローカル変数を定義し、その中に関数を持つことができます。内部関数(事実上インスタンスメソッド)はローカル変数(事実上インスタンス変数)にアクセスできますが、スクリプトの残りの部分から分離されます。

1
James Curran

自己実行機能は、変数のスコープを管理するために使用されます。

変数のスコープは、変数が定義されているプログラムの領域です。

グローバル変数にはグローバルスコープがあります。 JavaScriptコードのどこでも定義され、関数内であっても、スクリプト内のどこからでもアクセスできます。一方、関数内で宣言された変数は、関数の本体内でのみ定義されます。これらはローカル変数であり、ローカルスコープを持ち、その関数内でのみアクセスできます。関数パラメーターもローカル変数としてカウントされ、関数の本体内でのみ定義されます。

以下に示すように、関数内のglobalvariable変数にアクセスできます。また、関数の本体内では、ローカル変数が同じ名前のグローバル変数より優先されることに注意してください。

var globalvar = "globalvar"; // this var can be accessed anywhere within the script

function scope() {
    alert(globalvar);
    localvar = "localvar" //can only be accessed within the function scope
}

scope(); 

したがって、基本的に自己実行関数を使用すると、javascriptコードの他のブロックで変数の名前を指定する方法を気にせずにコードを記述できます。

1
(function(){
    var foo = {
        name: 'bob'
    };
    console.log(foo.name); // bob
})();
console.log(foo.name); // Reference error

実際、上記の関数は名前のない関数式として扱われます。

関数を閉じ括弧と開き括弧でラップする主な目的は、グローバルスペースの汚染を回避することです。

関数式内の変数と関数はプライベートになりました(つまり、関数の外部では使用できなくなります)。

0
Madhankumar

この質問に対する回答はすべて用意されているようですが、とにかく入力を投稿します。

いつ自己実行機能を使用したいかを知っています。

var myObject = {
    childObject: new function(){
        // bunch of code
    },
    objVar1: <value>,
    objVar2: <value>
}

この関数を使用すると、いくつかの追加コードを使用して、一般的に使用される変数の設定や数学の方程式の実行など、よりクリーンなコードのchildObjects属性とプロパティを定義できます。ああ!またはエラーチェック。ネストされたオブジェクトのインスタンス化構文に限定されるのではなく...

object: {
    childObject: {
        childObject: {<value>, <value>, <value>}
    }, 
    objVar1: <value>,
    objVar2: <value>
}

一般的にコーディングには、同じことをたくさん行う多くのあいまいな方法があり、「なぜわざわざ」と思わせます。しかし、基本的なプリンシパルやコアプリンシパルだけに頼ることができなくなった新しい状況が現れ続けています。

0
Garrett