59

JavaScript でローカル (内部) 関数が宣言されている場合、次の 2 つのオプションがあります。

キーワードで宣言しvar、変数に割り当てます。

(function() {
    var innerFunction1 = function() { ... };
    innerFunction1();
}());

function変数に代入せずに、キーワードだけで宣言します。

(function() {
    function innerFunction2() { ... };
    innerFunction2();
}());

2 番目の利点が 1 つあります。関数を呼び出すコードの下で関数を宣言できるため、実際に実行されるコードからプライベート関数を簡単に分離できます。

それらのどれがより良いですか、なぜですか?

4

11 に答える 11

47

実際には、関数を宣言する方法は 3 つあります。

  1. 関数宣言: 関数宣言は、変数の代入を必要とせずに名前付き関数変数を定義します。関数宣言はスタンドアロンの構造として発生し、非関数ブロック内にネストすることはできません。元:function innerFunction1 () { };

  2. 関数式: : 関数式は、より大きな式の構文 (通常は変数の代入) の一部として関数を定義します。関数式を介して定義された関数は、名前付きまたは匿名にすることができます。

    を。無名関数の使用 -var innerFunction1 = function() { };

    b. 名前付き関数の使用 -var innerFunction1 = function myInnerFunction () { };

  3. 関数コンストラクター: 関数コンストラクターは、Function( ) コンストラクターを使用して動的に関数を定義します。関数本体は文字列引数として関数に渡されることに注意してください。 var innerFunction1 = new Function (arg1, arg2, ... argN, functionBody)

関数本体を文字列として渡すと、一部の JS エンジンの最適化が妨げられる可能性があり、エラーが発生しやすいため、3 番目の方法はお勧めしません。

関数宣言と関数式の違いは微妙なので、要件に最も適した方法を選択する必要があります。

必要な場所で関数式を使用します

  1. シングルトン関数、または
  2. (名前付き関数式を使用して) プログラムで使用する関数を決定します。

関数宣言と関数式の違いは次のとおりです。

  1. 関数式を使用すると、同じ変数に異なるポイントで異なる関数を割り当てることができます。
  2. 関数宣言によって定義された関数は、関数宣言自体の前 (または基本的に現在のスコープ内の任意の場所) で使用できますが、関数式によって定義された関数は、それが定義された時点の後でしか使用できません。

関数宣言と関数式と関数コンストラクタ @MDNの詳細な比較を読むには、ここをクリックしてください

注:関数宣言は、var に代入することで簡単に関数式に変換できます。

function foo() {}
alert(foo); // alerted string contains function name "foo"
var bar = foo;
alert(bar); // alerted string still contains function name "foo"

もっと読む:

于 2013-05-14T17:38:15.260 に答える
8

2 つの表記法は機能的に同等です。

次のことが想定できます。

function a() {}
function b() {}

次のように解釈されます。

var a, b;
a = function a() {};
b = function b() {};

これが、使用前に宣言する必要がない (定義しない!) 理由です。変数の場合と同じように、定義後に関数を再割り当てできます。関数は変数であるため、変数と同じように巻き上げられます(マインド = 吹き飛ばされた? 良い!)。


使用前申告

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. 英語では「I will be using variable x .

定義: x = 5. 英語で「変数xは値を持つようになりました5 .

では使用前宣言が必須であり、強制されてい"use strict"ます。使用前定義は不要です。実行時に変数が定義されていれば問題ありません。

宣言var x = 5と定義の両方もfunction a() {}同様です。

関数に名前を付けるときは、既存の変数をオーバーライドしないように注意してください。

var a = function () { alert("a"); };
var b = function a() { alert("b"); };
a(); // prints "b"

Lintツールはこれに対応します。


どの表記をいつ使用するか?

後でvar a = function () {}の値を再割り当てする場合にのみ、関数式表記 ( ) を使用することをお勧めします。a次に、関数式は、a再割り当てされる予定であり、それが意図的であることをリーダーに通知します。

関数式表記のもう 1 つの (小さな) 引数は、JSLint のような Lint ツールです。関数を使用する前に、関数を宣言する (定義するのではなく!) 必要がある場合があります。再帰的な定義を持つ関数がある場合、つまり. acallsbbcallsaの場合、関数宣言表記を使用して一方を他方の前に宣言することはできません。

編集メモ:名前付き無名関数について少し修正しました。スタックトレースを見ているときに匿名関数に名前を付けると便利です。名前付き関数は、「匿名」としてログに記録されないように、より多くのコンテキストを提供します。

于 2013-05-18T02:05:01.853 に答える
2

出力に違いはありません。どちらも引き続き呼び出すことができ、両方のプロトタイプに名前でアクセスできます。

実際の違いは 2 つだけです。

1) 読みやすさと好み

ある方法の方が他の方法よりも読みやすいと感じる人もいれば、そのスタイルに基づいて規則を作成する人もいます。規則に従うことが重要です。

2)スペース

縮小化がスクリプトにとってますます重要になってきているため、2 番目のアプローチを使用することがどのように有利であるかがわかります。これは、縮小化されたスクリプトで基本的に取るに足らない 4 文字のスペースを使用する必要がないvarか、節約できるからです。=


エグゼクティブサマリー

それはすべて好みに帰着します。どちらが良いですか?教えてください。個人的には、それからvarオブジェクトを作成する場合に使用しnew、Person のように最初の文字を大文字にします。それ以外の場合、私はそれをキャメルケースにして、の使用を省略する傾向がありvarます。

于 2013-05-14T23:38:58.973 に答える
1

@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 が指摘したように、あるタイプを使用することにスコープ上の利点はないようです。

于 2013-05-17T08:22:20.190 に答える
1

ローカル宣言では、常に var を使用する必要があります。

それはローカルスコープであり、シンボルが使用されなくなった後にメモリがクリアされる可能性があるためです。

2番目のフォームは標準の一部ではないため、使用しないでください.

ブロック内の関数宣言

こんなことしないで:

if (x) { function foo() {} } ほとんどのスクリプト エンジンはブロック内の関数宣言をサポートしていますが、ECMAScript の一部ではありません (ECMA-262 の 13 節と 14 節を参照)。より悪い実装は、相互に一貫性がなく、将来の EcmaScript の提案とも矛盾しています。ECMAScript では、スクリプトまたは関数のルート ステートメント リストでの関数宣言のみが許可されます。代わりに、関数式で初期化された変数を使用して、ブロック内で関数を定義します。

もし (x) {

var foo = 関数() {}

}

ソースhttp://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml

于 2013-05-17T02:30:44.373 に答える
0

JavaScript 関数の定義

Vega が述べたように、関数を定義するには 3 つの方法があります。

  1. 関数コンストラクター
  2. 関数宣言
  3. 関数式

関数コンストラクターの短所:

関数コンストラクターは、関数本体を文字列として必要とします。

  • 一部の JS エンジンの最適化を妨げる可能性があります
  • 構文を書くのが信じられないほど難しくなります: 特殊文字やその他の狂気をエスケープする必要があります。以下を参照してください

    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.

関数宣言の短所:

関数宣言自体の前に呼び出すことができますが、これは実際には複雑さをもたらします。

関数式の利点:

関数式はより単純です。

  • どの変数に割り当てられているかを「知っている」
  • 関数が割り当てられている変数をその定義の前に呼び出し/参照することはできません。これは、残りの JavaScript 定義と一貫した動作です。

詳細: 関数宣言を関数式に変換する

危険: 「関数宣言の短所」で述べたように、これは多くの問題につながる可能性があります。以下に詳細を示します。

関数宣言を関数式に変換するのは非常に簡単です。

「関数宣言は、次のいずれかの場合に 1 つではなくなります: 式の一部になり、関数またはスクリプト自体の「ソース要素」ではなくなります。「ソース要素」は、スクリプトまたは関数内のネストされていないステートメントです。本体" 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();

注意すべきもう 1 つの点: 関数式はすぐに呼び出すことができますが、関数宣言はできません。この機能は IIFE で使用されます。詳しくは、「(function(){ … })()」のような無名関数で Javascript ファイル全体をラップする目的は何ですか? を参照してください。


資力

于 2014-11-05T16:50:16.340 に答える
0

JavaScript でプログラミングを始める人は誰しも、遅かれ早かれ自問自答すると思います。あなたの質問を次のように再定式化します。

関数宣言( function statement ) または関数式( var version)を使用する必要がありますか (使用することをお勧めします)?

ほとんどの場合、構造の 1 つだけを使用して適切な JavaScript コードを作成できます。セマンティックにいくつかの重要な違いがあることは明らかですが、私の意見では、質問に対する答えは主にプログラムのスタイルに関する答えであることを強調したいと思います。したがって、ほとんどの場合、選択は好みの問題であると私は答えます。

関数ステートメントを使用することを好む人は、読み取り専用の関数変数を定義する必要がある間はほとんど使用しません。使用する前に宣言したくない理由はありません。私の意見では、主にフォームが好きなので、それを使用します。

ですから、あなたの質問には客観的に正しい答えはないと思います。選択は主観的です。ですから、私が個人的に好む構造と、どの状況での回答を書いています。

私の最初の言語は、Pascal、C、Fortran、C++ などでした。現在は C# を使用していました。そのため、私が JavaScript プログラムを書き始めたとき、最初は別の言語からプログラムを作成する既存のスタイルを使用していました。後で、特定の言語に対応する JavaScript コードのスタイルを変更しました。

私は個人的に関数式スタイルを使用することを好み、外側の関数の最初のステートメントですべての関数を宣言します。関数の名前が変数である JavaScript セマンティックにはほとんど明確なフォームに関数値が含まれていることがわかりました。関数の名前は、他の変数と同様にホイストの対象となります。たとえば、私のコードは以下のようになります

(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() {
    "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) {
            ...
        };
    ...    
}());

wheremyFunc2は に追加で宣言されていmyFunc1ます。このようなフォームの実装は、Web ブラウザーに依存します。再帰関数を使用する場合は、おそらく意味があります。

于 2013-05-15T13:20:22.957 に答える
-3

簡単な答え:コードでは問題ありませんが、var読みやすくするために配置する必要があります。

長い答え: JavaScript のローカル変数は、JavaScript のグローバル変数と同様に、 を使用しても使用しなくても定義できますvar。したがって、プログラムの機能は、単語の欠落または存在によって妨げられることはありませんvar。を使用するとコードが読みやすくなるため、変数を最初に宣言するときに変数の前にvar配置することをお勧めします。しかし、読めないvarようにしたい場合は、変数を定義する前に置くべきではありません。var

于 2013-05-12T13:47:16.263 に答える