10

重複の可能性:
JavaScriptオブジェクト/関数/クラス宣言を囲む括弧はどういう意味ですか?
この「(function(){});」(角かっこ内の関数)は、JavaScriptで何を意味しますか?
Javascript関数

私はこれに似たマークアップに遭遇しました:

var something = (function(){
    //do stuff
    return stuff;
})()
document.ondblclick = function(e) { alert(something(e)) };

変数の開始(と終了)()がわかりません。somethingこのように書くことの違いを教えてください。

var something = function(){
    //do stuff
    return stuff;
};

ありがとう!

4

5 に答える 5

5

(function(){ ... })(無名の) 関数式です。たとえば、その値を変数に割り当てることができます。

その後ろの括弧は関数式を即座に実行し、関数の戻り値になります (ここでは: stuff)。この構造はIIFEと呼ばれます。

stuffが関数である場合 (後で呼び出すためだと思います) something、これはクロージャーと呼ばれます。返された関数 ( stuff、 に割り当てられてsomethingいる) は、その無名関数の実行コンテキスト内の変数に引き続きアクセスできます。

于 2012-08-03T12:49:51.010 に答える
5

冗長な括弧は何の役にも立たないため、省略した方が理解しやすいでしょう。

var something = function() {
    return 3;
} // <-- a function. 
(); // now invoke it and the result is 3 (because the return value is 3) assigned to variable called something 

console.log(something) //3 because the function returned 3 

var something = function() {
    return 3;
}; // a function is assigned to a variable called something

console.log(something) //logs the function body because it was assigned to a function
console.log(something()) //invoke the function assigned to something, resulting in 3 being logged to the console because that's what the function returns
于 2012-08-03T12:57:36.653 に答える
4

それが何をするのかという質問については、すべてのコメントと他の回答を読んでください。彼らは絶対に正しいです。

なぜそれを使いたいのですか?このパターンは、クロージャーを使用するときによく見られます。次のコード スニペットの目的は、10 個の異なる DOM 要素にイベント ハンドラーを追加し、それぞれがその ID 属性を警告することです (例: 「You've clicked 3」)。これが実際の意図である場合は、これを行うためのはるかに簡単な方法があることを知っておく必要がありますが、学術的な理由から、この実装に固執しましょう。

var unorderedList = $( "ul" );
for (var i = 0; i < 10; i++) {
    $("<li />", {
        id: i,
        text: "Link " + i,
        click: function() {
            console.log("You've clicked " + i);
        }
    }).appendTo( unorderedList );
}

上記のコードの出力は、最初に期待したものとは異なる場合があります。イベント ハンドラが起動された時点での i の値は「9」であるため、すべてのクリック ハンドラの結果は「You've clicked 9」になります。開発者が本当に望んでいたのは、イベント ハンドラーが定義された時点で i の値が表示されることです。

上記のバグを修正するために、クロージャを導入できます。

var unorderedList = $( "ul" ), i;

for (i = 0; i < 10; i++) {
    $("<li />", {
        id: i,
        text: "Link " + i,
        click: function(index) {
            return function() {
                console.log("You've clicked " + index);
            }
        }(i)
    }).appendTo( unorderedList );
}

上記のコードは jsFiddle から実行および変更できます。

上記のコードを修正する 1 つの方法は、自己実行型の無名関数を利用することです。これは、名前のない関数を作成してすぐに呼び出すことを意味する凝った用語です。この手法の価値は、変数のスコープが関数内にとどまることです。そのため、最初にイベント ハンドラの内容を関数で囲み、すぐに関数を呼び出して i の値を渡します。そうすることで、イベント ハンドラーがトリガーされたときに、イベント ハンドラーが定義されたときに存在していた i の値が含まれます。

クロージャに関する詳細情報: JavaScript クロージャのユース ケース

于 2012-08-03T12:45:43.463 に答える
1

JavaScript の FAQ セクションもチェックしてください:ここにかなり良い説明と例があります

わかりました、なぜこれを使うべきですか:

スクリプトが実行されていて、後で必要になる可能性のあるものがいくつかあるとします (たとえば、ノード リストをループ処理しています)。そのため、次のようなことを選択する場合があります。

for(var i=0;i<nodesList.lenght;i++)
{
    if (nodesList[i].id==="theOneINeed")
    {
        aClosure = (function(node,indexInNodesList)//assign here
        {
            return function()
            {
                node.style.display = 'none';//usable after the parent function returns
                alert(indexInNodesList+ ' is now invisible');
            }
        })(nodesList[i],i);//pass the element and its index as arguments here
        break;
    }
}
i = 99999;
aClosure();//no arguments, but it'll still work, and say i was 15, even though I've just 
//assigned another value to i, it'll alert '15 is now invisible'

これにより、関数の引数がガベージ コレクションされるのを防ぐことができます。通常、関数が戻った後、すべての var と引数が GC されます。しかし、この場合、関数はそれらの引数へのリンクを持つ別の関数を返した (それが必要です) ため、それらは存在する限り GC されませんaClosure

私のコメントで言ったように。Google クロージャーは、少し練習すればすぐに理解できるはずです...それらは本当に非常に強力です

于 2012-08-03T12:51:24.987 に答える
1

すべての回答は良好でしたが、最も単純な回答はざっと見ただけだと思います。

var something = (function(){
    //do stuff
    return stuff;
})()

このコードの実行後、 は にsomethingなりstuffます。何かが割り当てられる前に、何かを返した関数が実行されます。

var something = function(){
    //do stuff
    return stuff;
};

このコードの実行後、something を返す関数stuffです。何かを返す関数は実行されませんでした。

于 2012-08-03T13:03:24.790 に答える