JavaScriptでローカル(内部)関数が宣言されている場合、2つのオプションがあります。
var
キーワードで宣言し、変数に割り当てます:
(function() {
var innerFunction1 = function() { ... };
innerFunction1();
}());
変数に割り当てずに、function
キーワードのみで宣言する:
(function() {
function innerFunction2() { ... };
innerFunction2();
}());
2番目の利点の1つがわかります。関数は、それを呼び出すコードの下で宣言できるため、実際に実行されるコードからプライベート関数を簡単に分離できます。
どちらがbetterとwhy?
実際には、関数を宣言するには3つの方法があります。
関数宣言 :関数宣言は、変数の割り当てを必要とせずに名前付き関数変数を定義します。関数宣言はスタンドアロン構造として発生し、非関数ブロック内にネストすることはできません。例:function innerFunction1 () { };
関数式: :関数式は、より大きな式構文(通常は変数割り当て)の一部として関数を定義します。関数式で定義された関数は、名前を付けることも、匿名にすることもできます。
a。匿名関数の使用-var innerFunction1 = function() { };
b。名前付き関数の使用-var innerFunction1 = function myInnerFunction () { };
関数コンストラクター :関数コンストラクターは、Function()コンストラクターを使用して関数を動的に定義します。関数本体は、文字列引数として関数に渡されることに注意してください。 var innerFunction1 = new Function (arg1, arg2, ... argN, functionBody)
3番目の方法は、関数本体を文字列として渡すと一部のJSエンジンの最適化が妨げられ、エラーが発生する可能性があるため、お勧めしません。
関数宣言と関数式の違いは微妙であり、要件に最も適した方法を選択する必要があります。
必要な場所で関数式を使用します
関数宣言と関数式の違いは次のとおりです。
ここをクリックして、関数宣言vs関数式vs関数コンストラクタ@MDNの詳細比較を読む
注:関数宣言は、変数に代入することで簡単に関数式に変換できます。
function foo() {}
alert(foo); // alerted string contains function name "foo"
var bar = foo;
alert(bar); // alerted string still contains function name "foo"
その他の読み物:
2つの表記は機能的に同等です。
あなたはそれを仮定することができます:
_function a() {}
function b() {}
_
次のように解釈されます。
_var a, b;
a = function a() {};
b = function b() {};
_
これが、使用前に宣言する(定義しない!)必要がない理由です。変数を使用する場合と同様に、定義した関数を再割り当てできます。 変数であるため、関数は変数と同じように持ち上げられます(mind = blown?good!)。
使用前に宣言する
_function a() { b(); } // using b before it's declared?
function b() {}
_
になる:
_var a, b;
a = function a() { b(); }; // nope! b is declared, we're good
b = function b() {};
_
関数の再定義
_function a() { alert("a"); }
a = function b() { alert("b"); }; // that's weird!
_
になる:
_var a;
a = function a() { alert("a"); };
a = function b() { alert("b"); }; // oh, that looks normal
_
宣言と定義
宣言:_var x
_。英語: "変数x
"を使用します。
定義:_x = 5
_。英語 "変数x
の値は_5
_"になりました。
_"use strict"
_で使用前の宣言が必要であり、強制されています。使用前に定義する必要はありません。変数が実行時に定義されている場合は問題ありません。
_var x = 5
_はboth宣言と定義であり、function a() {}
も同様です。
既存の変数をオーバーライドしないように関数に名前を付けるときは注意してください:
_var a = function () { alert("a"); };
var b = function a() { alert("b"); };
a(); // prints "b"
_
Lint ツールはこれを取り上げます。
どの表記法を使用するか?
後でa
の値を再割り当てする場合にのみ、関数式表記(var a = function () {}
)を使用することをお勧めします。次に、関数式は、a
が再割り当てされることを意図していることをリーダーに通知します。
関数式表記のもう1つの(マイナー)引数は、JSLintのようなLintツールです。関数を使用する前に関数を宣言する(定義しない)必要がある場合があります。再帰的な定義を持つ関数がある場合、つまりa
がb
を呼び出し、b
がa
を呼び出します。関数宣言表記を使用して一方を他方より先に宣言することはできません。
ノートの編集:名前付き匿名関数について少し修正しました。スタックトレースを見ているときに、匿名関数に名前を付けると便利です。名前付き関数は、「匿名」としてログに記録されないように、より多くのコンテキストを提供します。
違いは、VAR
を持つ関数が実行時で定義されていることです。
一方、VARなしのfunction()は、スクリプトブロックのparse-timeで定義されます。
それが唯一の大きな違いです。
そのため、ユーザーは要件に基づいて、どちらを使用し、どちらが要件に適合するかを決定します。
出力に違いはありません。両方を呼び出すことができ、両方のプロトタイプに名前でアクセスできます。
本当の違いは2つだけです。
1)読みやすさと好み
一部の人々は、他の人よりも読みやすい方法を見つけ、そのスタイルに基づいて慣習を決定します。次の規則が重要です。
2)わずか省スペース
スクリプトに対して縮小化がこれまで以上に重要になっているため、var
または=
を使用する必要がないため、2番目のアプローチを使用する方が有利であることがわかります。縮小したスクリプトのスペース。
エグゼクティブサマリー
それはすべて好み次第です。どちらが良いですか?教えてください。個人的に、var
でオブジェクトを作成する場合は、new
を使用し、Personなどの最初の文字を大文字にします。そうでなければ、私はキャメルケースを使い、var
の使用を省略する傾向があります。
@MarmiKに同意します。 また、2つの方法の違いはスコープです。 関数宣言はデフォルトでローカルスコープを割り当てますが、変数に割り当てられた関数のスコープは変数のスコープに依存します。
var a;
(function() {
var innerFunction1 = function() { ... };//local scope
a=innerFunction1;//assigning to a global variable
}());
グローバルにアクセスできます。スコープを変更する必要がない場合は、関数宣言を使用してください。 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope
var a;
(function() {
function innerFunction1() { ... };//local scope
a=innerFunction1;//It works too(Don't know why it should though)
}());
したがって、@ Fritsが指摘したように、あるタイプを他のタイプよりも使用することには、スコープの利点はないようです。
var
関数名なし
var
なしの名前の関数:
var
で宣言されたクロージャー変数を使用すると、クロージャー変数が宣言される前にこの関数が呼び出されると失敗します。だから、あなたはあなたが何をすべきかを知る必要があります。var
の有無にかかわらず指定された関数
名前付きでvar
の関数
ローカル宣言では常にvarを使用する必要があります。
最初はローカルスコープであり、シンボルが使用されなくなった後にメモリをクリアできるため、最初の方が優れていると言えます。
また、google javascriptスタイルガイドには、2番目のフォームは標準の一部ではないため、使用しないでくださいというメモがあります。
ブロック内の関数宣言
こんなことしないで:
if(x){function foo(){}}ほとんどのスクリプトエンジンはブロック内の関数宣言をサポートしますが、ECMAScriptの一部ではありません(ECMA-262、13節および14節を参照)。さらに悪い実装は、互いに矛盾し、将来のEcmaScriptの提案と矛盾します。 ECMAScriptは、スクリプトまたは関数のルートステートメントリストでのみ関数宣言を許可します。代わりに、関数式で初期化された変数を使用して、ブロック内の関数を定義します。
if(x){
var foo = function(){}
}
ソース http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml 。
Vegaで述べたように、関数を定義するには3つの方法があります。
関数コンストラクターには、次の文字列としての関数本体が必要です。
構文を非常に記述しにくくします。特殊文字やその他の狂気をエスケープする必要があります。以下を参照してください
var foo = (new Function("var bar = \'FOO!\';\nreturn(function() {\n\talert(bar);\n});"))();
foo(); // The segment "function() {\n\talert(bar);\n}" of the function body string is not re-parsed.
関数宣言自体の前に呼び出すことができますが、これは実際には複雑さをもたらします。
関数式はより単純です:
危険:「関数宣言の短所」で述べたように、これは多くの問題につながる可能性があります。これについての詳細は以下にあります。
関数宣言を関数式に変換するのは非常に簡単です。
「関数宣言は、式の一部になると、関数またはスクリプト自体の「ソース要素」ではなくなります。「ソース要素」は、スクリプトまたは関数のネストされていないステートメントです。 body " https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Examples_2
「関数文は巻き上げの対象です。これは、関数がどこに配置されているかに関係なく、関数が定義されているスコープの最上部に移動することを意味します。 ifステートメントでの関数ステートメントの使用も禁止されています。ほとんどのブラウザーでは、ifステートメントで関数ステートメントを使用できますが、解釈方法が異なります。これにより、移植性の問題が発生します。 -本から: Javascript The Good Parts
構文は次のとおりです。
var varName = function [name]([param] [, param] [..., param]) { /* function expression */
statements
}
[name]
に関する注意事項(構文の「関数」の直後):
次に、[name]
を使用して、以下のような奇妙な/面白いことを行うことができます。 関数定義に慣れていない場合、これを行うことはお勧めしません。
var count = 0;
var varName = function funcName() { /* function expression */
console.log('count is: ' + count );
if(count<1){
count++;
funcName(); /* calls function funcName another time */
}
};
varName(); // invokes function funcName via variable varName
funcName(); // throws an error as funcName is not reachable
jsbin.com/gijamepesu/1/edit?js,console のライブデモをご覧ください
典型的な実装と使用法は次のようになります。
var myCoolFunc = function ( username, firstName, lastName ) { /* function expression */
console.log('user ' + username + ' has the real full name ' + firstName + ' ' + lastName);
}
myCoolFunc();
別の注意事項:関数式はすぐに呼び出すことができますが、関数宣言はできません。この機能はIIFEで使用されます。詳細は 「(function(){…})()」などの匿名関数でJavascriptファイル全体をラップする目的は何ですか?
JavaScriptでプログラミングを始めた人はだれでも、遅かれ早かれ自分自身に質問をすると思います。あなたの質問を次のように再定式化します。
関数宣言(関数ステートメント)または関数式(varバージョン)を使用する必要がありますか?
ほとんどの場合、構成から1つだけを使用して適切なJavaScriptコードを記述できます。セマンティックにいくつかの重要な違いがあることは明らかですが、私が強調したいのは、私の意見では、質問に対する答えは主にプログラムのスタイルに関する答えです。 ほとんどの場合選択肢は好みの問題です。
function statementを使用することを好む人は、readonly関数変数を定義する必要がある間はほとんど使用せず、使用する前に宣言したくない理由もありません。私の意見では、1つはlikes形式であるため、ほとんどの場合それを使用します。
ですから、あなたの質問にはobjectively正解はないと思います。選択はsubjectiveです。それで、私は個人的にどちらの構造を好み、どの状況で使用するかを答えに書きます。
私の最初の言語はPascal、C、Fortran、C++などでした。今ではC#を使用していました。ですから、JavaScriptプログラムを書き始めたとき、最初に既存のスタイル別の言語のプログラムを書くことに使いました。後で、特定の言語に対応するJavaScriptコードのスタイルを変更しました。
I 個人的に関数式スタイルを使用することを好み、外部関数の最初のステートメントですべての関数を宣言します。関数の名前が変数であるJavaScriptセマンティックに対して、フォームがほとんど明確であることがわかりました。関数の名前は、他の変数と同様に hoisting に従います。たとえば、私のコードは次のようになります
(function() {
"use strict";
var myFunc1 = function (x) {
// body where I can use x and this
alert("x=" + x + ", this.foo=" + this.foo);
},
localVar1 = {foo: "bar"};
myFunc1.call(localVar1, 1);
}());
function statementを使用することはほとんどありません。クラスのコンストラクタを次のように宣言する場合のみです。
(function() {
"use strict";
function MyClass(x) {
// the code of constructor
this.abc = x;
}
var myInstance = new MyClass("xyz");
alert(myInstance.abc);
}());
3番目の形式を使用しないでください。
(function() {
"use strict";
var myFunc1 = function myFunc2(x) {
...
};
...
}());
ここで、myFunc2
はmyFunc1
に追加で宣言されます。そのようなフォームの実装は、Webブラウザに依存します。再帰関数を使用する場合にはおそらく意味があります。
Zakasは、「関数を使用する前に常に関数を定義する限り、関数宣言または関数式を自由に使用できます」と述べています。
明日あなたのコードがいつか知らない人によって明日変更され、それが開発者が関数が宣言されている場所を見つけることができない大きなプロジェクトである場合、関数宣言を使用する必要があります(つまり、関数x(){} )、またはとにかく関数を最初に宣言する場合は、式を使用できます。