

JavaScriptでの関数定義には2つあるみたいですが、違いや使い分けがわからないので教えて下さい。

パターン1

[code]

    function hoge(a, b) {
        ...
    }
    
[/code]

パターン2

[code]

    var hoge = function(a, b) {
        ...
    }
    
[/code]

どちらも実行するときは`hoge(a, b);`でよいのでしょうか。


CC BY-SA 3.0
2014-12-29T08:53:15.700
2781
2014-12-30T05:46:52.070
2014-12-29T10:59:07.713
85
5855
question
javascript
function hoge() と hoge = function() の違いは？


違いはいつ定義されるかという点です。以下の例で`functionOne`は実行時に定義されますが、`functionTwo`は構文解析時に定義されます。

[code]

    <script>
      // Error
      functionOne();
    
      var functionOne = function() {
      };
    </script>
    
    <script>
      // No error
      functionTwo();
    
      function functionTwo() {
      }
    </script>
    
[/code]

また、`functionTwo`の定義方法では、strictモードの場合、条件節と共に使用することができなくなります。

[code]

    <script>
      "use strict";
      if (test) {
         // Error
         function functionThree() { doSomething(); }
      }
    </script>
    
[/code]

この例でもし`"use strict"`がなければエラーにはならず、`functionThree`は`test`の値に関係なく、定義されることになります。

* * *

この回答は、英語版にある同様の質問に対する@Gregさんの正解回答を簡易的に訳したものです。

[javascript - var functionName = function() {} vs function functionName() {} -
Stack Overflow](https://stackoverflow.com/questions/336859/var-functionname-
function-vs-function-functionname)


CC BY-SA 3.0
2014-12-29T09:01:54.480
2782
2014-12-29T09:15:47.257
2017-05-23T12:38:56.083
-1
3313
2781
answer


パターン2の使い道は、主にコールバックです。  
関数を数値や文字列同様、変数に代入できます、ということは、関数に引数として渡すことも可能です。  
非同期処理などで何か行い、完了時に知らせて欲しい場合は、次のようにコールバックすることができます。

[code]

    var hoge = function(a, b) {
       alert( "Completed." );
    };
    
    call( hoge );
    
    function call( callback ){
        // 何かいろいろを非同期などで…
        callback( 100 , 200 ); // コールバックする
    }
    
[/code]


CC BY-SA 3.0
2014-12-29T09:08:36.390
2783
2014-12-29T09:08:36.390
2207
2781
answer


定義されるタイミングの違いについてmozillaに説明がありました。

<https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Statements/function>

これは実行されますが:

[code]

    hoisted(); // logs "foo"
    
    function hoisted() {
      console.log("foo");
    }
    
[/code]

これは実行されません:

[code]

    notHoisted(); // TypeError: notHoisted is not a function
    
    var notHoisted = function() {
       console.log("bar");
    };
    
[/code]

また、再帰したい場合などではパターン2の場合でも名前をつける場合があります:

[code]

    var math = {
      'factorial': function factorial(n) {
        if (n <= 1)
          return 1;
        return n * factorial(n - 1);
      }
    };
    
[/code]


CC BY-SA 3.0
2014-12-29T09:10:53.703
2784
2014-12-29T09:10:53.703
62
2781
answer


実行するときは hoge() でかまいません。どちらも同じ関数として扱うことができます。

違いは、「その行の実行時に関数が定義される」か、それとも「ファイルの読み込み時（パース時）に関数が定義されるか」です。

[code]

    function hoge(a, b) {
        // この関数は Javascript が読み込まれたときに定義される
    }
    
    var hoge = function(a, b) {
        // この関数は変数 hoge の文が実行されるときに始めて定義される
    }
    
[/code]

[この質問にあります](https://ja.stackoverflow.com/questions/2252/for%E3%83%AB%E3%83%BC%E3%83%97%E5%86%85%E3%81%AE%E9%96%A2%E6%95%B0%E4%BD%9C%E6%88%90%E3%82%92%EF%BC%AE%EF%BC%A7%E3%81%AB%E3%81%99%E3%82%8B%E7%90%86%E7%94%B1)が、「ループの中で関数を定義するな」というのが、Javascript
の書き方で推奨されていたりします。  
その理由の一つもこれです。ループの中で、

[code]

    for (i = 0; i < 100; i++) {
        var hoge = function(a, b) {
            ...
        }
    }
    
[/code]

と定義してしまうと、実行時に始めて関数が100回定義されてしまうため、パターン１よりも負荷が高くなってしまいがちです。

参考: [var functionName = function() {} vs function functionName()
{}](https://stackoverflow.com/questions/336859/var-functionname-function-vs-
function-functionname)


CC BY-SA 3.0
2014-12-29T09:11:09.390
2785
2014-12-29T09:16:09.937
2017-05-23T12:38:55.307
-1
4978
2781
answer


[3100さん](https://ja.stackoverflow.com/a/2782/3974)のに[同英語版の別解答](https://stackoverflow.com/a/338053/4366452)から付け足すと、パターン1はhogeという名の関数を宣言してますが、パターン2では無名関数を宣言し、それを変数hogeに入れていることになります。これが実用上で起こせる違いとしては、

[code]

    var hoge = function(){};
    
[/code]

とするとスコープはローカルですが、

[code]

    hoge = function(){};
    
[/code]

とすることでグローバルに定義できます。  
変数を使うことでeval()内で使ってもスコープが何処だかはっきりするので、デバッグが楽であり、ブラウザ間での互換性を保つことが出来ます（eval内で関数宣言するとブラウザごとに宣言される位置が違うらしい…）。

またパターン2は無名関数なので、Function.name( **非標準、IEはサポートしてません** )が以下のように空文字になります。

[code]

    function hoge1(){};
    var hoge2 = function(){};
    console.log(hoge1.name);//"hoge1"
    console.log(hoge2.name);//""
    
[/code]


CC BY-SA 3.0
2014-12-29T09:24:57.870
2786
2014-12-29T09:38:10.240
2017-05-23T12:38:56.083
-1
3974
2781
answer


両者の本質的な違いは、「式（`Expression`）」か「文（`Statement`)」かだと考えます。

# 関数定義式

パターン2の書き方は _関数定義式_ と呼びます。

[code]

    var hoge = function(a, b) {
        ...
    }
    
[/code]

JavaScriptには **巻上げ** という特異な仕様があり、実際には上の記述は以下のように分解されます。

[code]

    // varの宣言はスクリプトまたは関数の行頭で行われる（巻上げ）
    var hoge;
    // この時点でhogeへアクセスするとundefined
    hoge = function(a, b) {
        ...
    }
    
[/code]

また、ここで行われている処理は、匿名関数を変数`hoge`へ代入する処理です。`hoge()`で実行することはできますが、この関数自体が`hoge`という名前は持っていません。

名前を持たせるためには、以下のように宣言する必要があります。

[code]

    var hoge = function fuga(a, b) {
        // この中ではfuga()で再帰処理を書くことができる
        ...
    }
    // 外側ではhogeはfugaの名前を持つが、呼び出すときはhoge()を用いる
    hoge.name // => "fuga"
    
[/code]

# 関数宣言文

対して、パターン1の書き方は _関数宣言文_ と呼ばれます。

[code]

    function hoge(a, b) {
        ...
    }
    
[/code]

**文の巻上げは関数定義そのものに発生する** という特徴があり、その結果、スコープ内であればどこからでも呼び出すことができます。

また、関数宣言文で定義した関数は、必ず名前を持つという特徴があります。


CC BY-SA 3.0
2014-12-29T16:52:21.010
2809
2014-12-29T17:25:27.080
2014-12-29T17:25:27.080
5337
5337
2781
answer


挙動の違いは少なくて実質交換可能でも、意味としての違いがあります。  
例えばオブジェクトにいろいろ入れて返すような場合、つまり関数を値として生成したい場合はパターン2で書かれると思います。  
一方、その関数を関数内で使いたい場合、つまり関数を関数として設置したい場合はパターン１で書かれると思います。  
まあ挙動の差があまりないので、気分で変えたり、なるべくどちらかに統一しているような人も多いかもしれません。

因みに挙動の差としては巻き上げの他に、パターン１ではブロックスコープになるということがあります。

[code]

    (function () {
      "use strict"
      var fn = function () { return 1 }
      {
        function fn() { return 2 }
        console.log( fn() )  // 2
      }
      console.log( fn() )  // 1
    })()
    
[/code]


CC BY-SA 3.0
2014-12-29T19:17:52.713
2810
2014-12-30T05:46:52.070
2014-12-30T05:46:52.070
5721
5721
2781
answer