387

私はクロージャに関するいくつかの投稿を読んでいて、これをどこでも見ましたが、それがどのように機能するかについての明確な説明はありません-私がちょうどそれを使用するように言われたたびに...:

// Create a new anonymous function, to use as a wrapper
(function(){
    // The variable that would, normally, be global
    var msg = "Thanks for visiting!";

    // Binding a new function to a global object
    window.onunload = function(){
        // Which uses the 'hidden' variable
        alert( msg );
    };
// Close off the anonymous function and execute it
})();

OK、新しい無名関数を作成して実行することがわかりました。したがって、その後、この単純なコードは機能するはずです(そして機能します):

(function (msg){alert(msg)})('SO');

私の質問は、ここでどのような魔法が起こるのかということです。私が書いたとき、私は思った:

(function (msg){alert(msg)})

次に、関数 ""(msg)..のように名前のない新しい関数が作成されます。

しかし、なぜこれが機能しないのですか?

(function (msg){alert(msg)});
('SO');

なぜ同じ行にある必要があるのですか?

いくつかの投稿を教えていただけますか、それとも説明をお願いします。

4

19 に答える 19

383

関数定義の後にセミコロンをドロップします。

(function (msg){alert(msg)})
('SO');

上記は機能するはずです。

デモページ:https ://jsfiddle.net/e7ooeq6m/

この投稿では、この種のパターンについて説明しました。

jQueryと$の質問

編集:

ECMAスクリプトの仕様を見ると、関数を定義する方法は3つあります。(98ページ、セクション13関数定義)

1.関数コンストラクターの使用

var sum = new Function('a','b', 'return a + b;');
alert(sum(10, 20)); //alerts 30

2.関数宣言を使用します。

function sum(a, b)
{
    return a + b;
}

alert(sum(10, 10)); //Alerts 20;

3.関数式

var sum = function(a, b) { return a + b; }

alert(sum(5, 5)); // alerts 10

それで、あなたは尋ねるかもしれません、宣言と表現の違いは何ですか?

ECMAスクリプト仕様から:

FunctionDeclaration:関数識別子(FormalParameterListopt){FunctionBody}

FunctionExpression:function Identifieropt(FormalParameterListopt){FunctionBody}

お気づきの方もいらっしゃると思いますが、関数式では「識別子」はオプションです。また、識別子を指定しない場合は、無名関数を作成します。識別子を指定できないという意味ではありません。

これは、以下が有効であることを意味します。

var sum = function mySum(a, b) { return a + b; }

注意すべき重要な点は、「mySum」はmySum関数本体の内側でのみ使用でき、外側では使用できないことです。次の例を参照してください。

var test1 = function test2() { alert(typeof test2); }

alert(typeof(test2)); //alerts 'undefined', surprise! 

test1(); //alerts 'function' because test2 is a function.

ライブデモ

これをと比較してください

 function test1() { alert(typeof test1) };

 alert(typeof test1); //alerts 'function'

 test1(); //alerts 'function'

この知識を身につけて、コードを分析してみましょう。

次のようなコードがある場合、

    function(msg) { alert(msg); }

関数式を作成しました。また、この関数式は括弧で囲んで実行できます。

    (function(msg) { alert(msg); })('SO'); //alerts SO.
于 2009-07-16T20:28:36.860 に答える
132

これは、自己呼び出し関数と呼ばれます。

呼び出し時に行っていること(function(){})は、関数オブジェクトを返すことです。それに追加()すると、それが呼び出され、本体のすべてが実行されます。は;ステートメントの終わりを示します。そのため、2 回目の呼び出しは失敗します。

于 2009-07-16T20:30:41.003 に答える
94

私がややこしいと思ったのは、「()」がグループ化演算子であることです。

これが基本的な宣言された関数です。

元。1:

var message = 'SO';

function foo(msg) {
    alert(msg);
}

foo(message);

関数はオブジェクトであり、グループ化できます。それでは、関数を括弧で囲みます。

元。2:

var message = 'SO';

function foo(msg) {  //declares foo
    alert(msg);
}

(foo)(message);     // calls foo

同じ関数を宣言してすぐに呼び出す代わりに、呼び出すときに基本的な置換を使用して宣言できます。

元。3.

var message = 'SO';

(function foo(msg) {
    alert(msg);
})(message);          // declares & calls foo

最後に、名前を使用して呼び出していないため、余分な foo は必要ありません。関数は匿名にすることができます。

元。4.

var message = 'SO';

(function (msg) {   // remove unnecessary reference to foo
    alert(msg);
})(message);

あなたの質問に答えるには、例 2 を参照してください。最初の行では、名前のない関数を宣言してグループ化していますが、それを呼び出していません。2 行目は文字列をグループ化します。どちらも何もしません。(Vincent の最初の例)

(function (msg){alert(msg)});  
('SO');                       // nothing.

(foo); 
(msg); //Still nothing.

しかし

(foo)
(msg); //works
于 2011-04-20T20:05:43.670 に答える
7

以前のコメントを要約すると:

function() {
  alert("hello");
}();

変数に割り当てられていない場合、構文エラーが発生します。コードは関数ステートメント (または定義) として解析されるため、閉じ括弧が構文的に正しくありません。関数部分の周りに括弧を追加すると、インタープリター (およびプログラマー) に、これが関数式 (または呼び出し) であることが次のように伝えられます。

(function() {
  alert("hello");
})();

これは自己呼び出し関数です。つまり、宣言されているのと同じ行で呼び出しが行われるため、匿名で作成され、すぐに実行されます。この自己呼び出し関数は、引数のない関数を呼び出すおなじみの構文で示され、さらに関数名の周りに括弧が追加されています(myFunction)();

SO の良い議論 JavaScript 関数構文があります。

于 2011-12-29T17:21:09.893 に答える
4

括弧なしの例:

void function (msg) { alert(msg); }
('SO');

(これは void の唯一の実際の使用方法です)

また

var a = function (msg) { alert(msg); }
('SO');

また

!function (msg) { alert(msg); }
('SO');

同様に動作します。これvoidにより、代入とバングだけでなく、式が評価されます。最後のものは~+-deletetypeof、いくつかの単項演算子 (voidも 1 つ) で動作します。変数が必要なため、++機能しないのは当然です。--

改行は必要ありません。

于 2015-04-23T18:13:55.980 に答える
4

質問者の質問に対する私の理解は次のとおりです。

この魔法はどのように機能しますか:

(function(){}) ('input')   // Used in his example

私は間違っているかもしれません。ただし、人々が慣れ親しんでいる通常の慣行は次のとおりです。

(function(){}('input') )

その理由は、JavaScript の括弧 AKA()にはステートメントを含めることができず、パーサーが function キーワードに遭遇すると、それを関数宣言ではなく関数式として解析することを認識しているためです。

出典: ブログ投稿即時呼び出し関数式 (IIFE)

于 2013-05-01T04:26:29.187 に答える
3

この回答は質問と厳密には関連していませんが、この種の構文機能は関数に固有のものではないことを知りたいと思うかもしれません。たとえば、私たちはいつでも次のようなことをすることができます:

alert(
    {foo: "I am foo", bar: "I am bar"}.foo
); // alerts "I am foo"

関数に関連します。これらはFunction.prototypeから継承するオブジェクトであるため、次のようなことができます。

Function.prototype.foo = function () {
    return function () {
        alert("foo");
    };
};

var bar = (function () {}).foo();

bar(); // alerts foo

また、関数を実行するために関数を括弧で囲む必要はありません。とにかく、結果を変数に割り当てようとする限り。

var x = function () {} (); // this function is executed but does nothing

function () {} (); // syntax error

関数を宣言するとすぐに、関数で実行できるもう1つのことは、関数に対してnew演算子を呼び出してオブジェクトを取得することです。以下は同等です。

var obj = new function () {
    this.foo = "bar";
};

var obj = {
    foo : "bar"
};
于 2009-07-16T21:10:09.537 に答える
3

JavaScript関数が持つもう1つのプロパティがあります。同じ無名関数を再帰的に呼び出したい場合。

(function forInternalOnly(){

  //you can use forInternalOnly to call this anonymous function
  /// forInternalOnly can be used inside function only, like
  var result = forInternalOnly();
})();

//this will not work
forInternalOnly();// no such a method exist
于 2011-10-17T06:20:11.050 に答える
1

無名関数は、実行時に動的に宣言される関数です。通常の関数と同じように名前が付けられないため、無名関数と呼ばれます。

無名関数は、関数宣言の代わりに関数演算子を使用して宣言されます。関数演算子を使用して、式を配置できる場所であればどこでも新しい関数を作成できます。たとえば、新しい関数を関数呼び出しのパラメーターとして宣言したり、別のオブジェクトのプロパティを割り当てたりすることができます。

名前付き関数の典型的な例を次に示します。

function flyToTheMoon() {
    alert("Zoom! Zoom! Zoom!"); 
}

flyToTheMoon(); 

以下は、無名関数として作成された同じ例です。

var flyToTheMoon = function() {
   alert("Zoom! Zoom! Zoom!"); 
}

flyToTheMoon();

詳細については、 http://helephant.com/2008/08/23/javascript-anonymous-functions/を参照してください。

于 2015-10-12T06:11:04.170 に答える
1

あなたがしたとき:

(function (msg){alert(msg)});
('SO');

('SO')セミコロンのため、前に関数を終了しました。あなたがちょうど書くなら:

(function (msg){alert(msg)})
('SO');

それが動作します。

作業例: http://jsfiddle.net/oliverni/dbVjg/

于 2013-11-29T21:56:22.723 に答える
1

;機能しない単純な理由は、無名関数の終わりを示すためではありません。これは()、関数呼び出しの最後に がないと、関数呼び出しではないためです。あれは、

function help() {return true;}

これを呼び出すresult = help();と、関数の呼び出しになり、true が返されます。

あなたが電話result = help;するなら、これは電話ではありません。ヘルプを結果に代入するデータのように扱う代入です。

あなたがしたことは、セミコロンを追加して匿名関数を宣言/インスタンス化することでした。

(function (msg) { /* Code here */ });

そして、括弧だけを使用して別のステートメントでそれを呼び出そうとしました...明らかに、関数には名前がないためですが、これは機能しません:

('SO');

インタープリターは 2 行目の括弧を新しい命令/ステートメントと見なすため、次のようにしても機能しません。

(function (msg){/*code here*/});('SO');

それでも機能しませんが、インタープリターが空白と改行を無視し、完全なコードを 1 つのステートメントと見なすため、セミコロンを削除すると機能します。

(function (msg){/*code here*/})        // This space is ignored by the interpreter
('SO');

()結論: 関数呼び出しは、別の関数によって呼び出されるなどの特定の条件下でない限り、最後に onがない関数呼び出しではありません。つまり、 onload='help' は、括弧が含まれていなくてもヘルプ関数を実行します。setTimeout と setInterval もこのタイプの関数呼び出しを許可すると思います。また、インタープリターが舞台裏で括弧を追加すると、「関数呼び出しは括弧なしの関数呼び出しではない」に戻ると思います。

于 2013-10-12T12:50:41.693 に答える
1

別の視点

まず、無名関数を宣言できます。

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

次に、次のように呼び出します。

foo ('Few');

foo = function(msg){alert(msg);}であるため、 fooを次のように置き換えることができます。

function(msg){
 alert(msg);
} ('Few');

ただし、解析時に関数を宣言する構文エラーを回避するために、無名関数全体を中かっこのペアで囲む必要があります。次に、

(function(msg){
 alert(msg);
}) ('Few');

このように、私には簡単に理解できます。

于 2013-06-21T15:15:30.017 に答える
-1

匿名関数は、提供している入力から出力を生成するようにその場で関数を定義するワンショット取引であることを意図しています。あなたが入力を提供しなかったことを除いて。代わりに、2 行目に何かを書きました ('SO')。- 機能とは関係のない独立したステートメント。何を期待していましたか?:)

于 2013-04-23T16:51:15.233 に答える