匿名のJavaScript関数を自動実行するための括弧の場所は?


107

最近、json2.jsの現在のバージョンとプロジェクト内のバージョンを比較していたところ、関数式の作成方法と自己実行方法に違いがありました。

匿名関数を括弧で囲んで実行するためのコード、

(function () {
  // code here
})();

しかし現在は、自動実行される関数を括弧で囲んでいます。

(function () {
  // code here
}());

Explain JavaScriptのカプセル化された匿名関数構文の受け入れられた回答にCMSによるコメントがあり、「両方:(function(){})();かつ(function(){}());有効です」。

違いは何だろうと思っていましたか?前者はグローバルな匿名関数を残してメモリを消費しますか?括弧はどこに置くべきですか?



関連:即時関数呼び出し構文(JSLint中)
Bergi

1
また、この構造目的について読むか、(技術的な説明を確認してください(ここでも)。括弧が必要な理由については、この質問を参照してください。
Bergi、2014

回答:


66

それらは事実上同じです。

1つ目は、関数を括弧で囲んで有効な式にしてから呼び出します。式の結果は未定義です。

2番目は関数を実行し、自動呼び出しを囲む括弧はそれを有効な式にします。また、未定義と評価されます。

表現の結果は同じなので、「正しい」方法はないと思います。

> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"

8
JSLintは「(function(){}());」を必要としています。JSLintは、「呼び出しを関数を含む括弧に移動します」と述べています。
XP1、2011

27
実際には、これら2つに限定されず、+function(){}()またはなど、ステートメントではなく関数が式の一部であることをコンパイラーに認識させるものであれば何でも使用できます!function(){}()
Tgr

49
@ XP1:JSLint は、実質的なものではなく、クロックフォードのスタイルに固有の多くのものを求めています。これはその1つです。
TJクラウダー2011

@TJCrowder。あなたは何をお勧めします?jQueryは最初のスタイルを使用し、Crockfordは2番目のスタイルを使用します。
Teej

4
@ThorpeObazee:それは本当に問題ではないので、好きなことをしてください。私は(もっとOUTREなもののいくつかに対して、お勧めしたい-function(){}();!function(){}();直前、および基本的に他のオペレータfunctionも仕事を、私は括弧を使用したバージョンに固執するだろう)。最初のものは2番目のものよりも多く表示されます。それが私の好みです。それも私にはもっと理にかなっていますが、それは主観的です。FWIW:jsbin.com/ejaqow
TJ Crowder

13

その場合、それは問題ではありません。最初の定義で関数に解決される式を呼び出し、2番目の例では関数を定義してすぐに呼び出しています。最初の例の関数式は単なる関数定義なので、これらは似ています。

関数に解決される式を呼び出す場合、他にも明らかに役立つケースがあります。

(foo || bar)()

3
他の読者への説明のために(主に私が最初にそれを理解しなかったので:))、fooおよび/またはbarはすでにいくつかの関数に等しい必要があります。(例えばfoo = function(){alert('hi');}。もしエラーがスローされ、関数でもない。
アレクサンダー・バード

3
@AlexanderBirdさらなる説明- foo関数ではなく「真実」である場合にもエラーをスローします。
JLRishe 2014

9

構文以外に違いはありません。

それを行う2番目の方法についてのあなたの懸念について:

検討してください:

(function namedfunc () { ... }())

namedfunc名前を指定しても、グローバルスコープには含まれません。匿名関数についても同様です。そのスコープでそれを取得する唯一の方法は、括弧内の変数に割り当てることです。

((namedfunc = function namedfunc () { ... })())

外側の括弧は不要です:

(namedfunc = function namedfunc () { ... })()

しかし、とにかくそのグローバル宣言を望まなかったのですか?

つまり、次のようになります。

(function namedfunc () { ... })()

そして、あなたはそれをさらに減らすことができます:名前は決して使用されないので不要です(関数が再帰的でない限り、そしてそれでも使用できますarguments.callee

(function () { ... })()

それが私の考えです(正しくない可能性があります。ECMAScript仕様をまだ読んでいません)。それが役に立てば幸い。


arguments.calleeES5ので、非推奨(および厳密モードで禁止)されます。
nyuszika7h

「外側の括弧は不要です。」-ファイルを連結するときのエラーを防ぐことができると思います。それ以外の場合は、!か何か。
Jimmyt1988

-3

ダグラス・クロックフォードIIFEの最初のスタイルを好まないため、違いが存在します。(seriuosly)このビデオでわかるように!!

(){両方のスタイルで} 余分なラッピングが存在する唯一の理由は、関数宣言をすぐに呼び出すことができないため、コードのそのセクションを関数式にするためです。縮小化-ERSだけで使用することをいくつかのスクリプト/ 、、&の代わりにあまりにもカッコ。このような:+!-~

+function() {  
    var foo = 'bar';  
}();

!function() {  
    var foo = 'bar';  
}();

-function() {  
    var foo = 'bar';  
}();

~function() {  
    var foo = 'bar';  
}();

そして、これらはすべて、代替案とまったく同じです。これらのケースの中から選択することは完全にあなた自身であり、違いはありません。{のファイルは1バイト大きいファイル()生成します ;-)}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.