web-dev-qa-db-ja.com

JavaScriptでローカル関数を定義する:varを使用するかどうか

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

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

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

変数に割り当てずに、functionキーワードのみで宣言する:

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

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

どちらがbetterwhy

57
Pavel S.

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

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

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

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

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

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

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

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

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

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

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

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

ここをクリックして、関数宣言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"

その他の読み物:

44

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ツールです。関数を使用する前に関数を宣言する(定義しない)必要がある場合があります。再帰的な定義を持つ関数がある場合、つまりabを呼び出し、baを呼び出します。関数宣言表記を使用して一方を他方より先に宣言することはできません。

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

7
Halcyon

違いは、VARを持つ関数が実行時で定義されていることです。

一方、VARなしのfunction()は、スクリプトブロックのparse-timeで定義されます。

それが唯一の大きな違いです。

そのため、ユーザーは要件に基づいて、どちらを使用し、どちらが要件に適合するかを決定します。

4
MarmiK

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

本当の違いは2つだけです。

1)読みやすさと好み

一部の人々は、他の人よりも読みやすい方法を見つけ、そのスタイルに基づいて慣習を決定します。次の規則が重要です。

2)わずか省スペース

スクリプトに対して縮小化がこれまで以上に重要になっているため、varまたは=を使用する必要がないため、2番目のアプローチを使用する方が有利であることがわかります。縮小したスクリプトのスペース。


エグゼクティブサマリー

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

2
Travis J

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

1
Binu Pandian
  • var関数名なし

    • 変数宣言をマスターする方が良いです:特にwhen宣言されます。


  • varなしの名前の関数:

    • 現在のスコープの先頭にある名前の変数宣言を意味し、エラーを防ぐことができます。
    • but:この方法で関数を宣言し、varで宣言されたクロージャー変数を使用すると、クロージャー変数が宣言される前にこの関数が呼び出されると失敗します。だから、あなたはあなたが何をすべきかを知る必要があります。


  • varの有無にかかわらず指定された関数

    • クラス宣言に適しています、
    • また、プロファイリングの原因については、たとえば、Chrome devプロファイリングツールは、関数が匿名でない場合、より明示的になります。関数は明示的な名前を持ち、コードの遅い部分がどこにあるかがわかります。


  • 名前付きでvarの関数

    • 宣言された変数をクロージャとして持たずに、関数を名前付きスコープとして使用する方法です
    • 変数宣言の順序をマスターし続けます。
1
lib3d

ローカル宣言では常に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

1
cavila

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定義と一貫した動作です。

詳細:関数宣言から関数式への変換

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

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

「関数宣言は、式の一部になると、関数またはスクリプト自体の「ソース要素」ではなくなります。「ソース要素」は、スクリプトまたは関数のネストされていないステートメントです。 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は省略できます。この場合、関数はanonymous function
  • 「関数名は変更できませんが、関数が割り当てられている変数は再割り当てできます。」
  • 「関数名は、関数の本体内でのみ使用できます。」 、この機能を使用して、関数が自身を再帰的に呼び出すことができます。

次に、[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ファイル全体をラップする目的は何ですか?


資源

0
Adrien Be

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

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

0
Oleg

Zakasは、「関数を使用する前に常に関数を定義する限り、関数宣言または関数式を自由に使用できます」と述べています。

明日あなたのコードがいつか知らない人によって明日変更され、それが開発者が関数が宣言されている場所を見つけることができない大きなプロジェクトである場合、関数宣言を使用する必要があります(つまり、関数x(){} )、またはとにかく関数を最初に宣言する場合は、式を使用できます。

0
cenk ebret