25394


**下記一.二.はそれぞれ何が違うでしょうか？**  
・それぞれメリットデメリットあれば教えてください

* * *

**ブラウザ以外**  
・一.はブラウザ以外でもaがグローバル変数になるので、一の方が良い？

**ブラウザの場合、同じ意味？**  
・普通はどちらを使うとかあるでしょうか？

* * *

**一.**

[code]

    (function() {
     a = 1;
    })()
    console.log(a); //1
    
[/code]

**二.**

[code]

    (function() {
     window.a = 1;
    })()
    console.log(a); //1
    
[/code]

* * *

**あるいは、下記のような書き方の方が良いでしょうか？**

[code]

    var a;
    (function() {
     a = 1;
    })()
    console.log(a); //1
    
[/code]


CC BY-SA 3.0
2016-06-02T15:06:47.103
25392
2016-06-02T19:12:02.650
7886
question
javascript
ローカルエリア内でグローバル変数定義する際、「a = 1;」「window.a = 1;」では何が違う？


> あるいは、下記のような書き方の方が良いでしょうか？

グローバル変数を使用する場合でも、変数の宣言はした方が無難です。(理由は後述)

また、変数のスコープは短ければ短いほど良いので、可能な場合はグローバル変数を避けたほうがいいです。

グローバル変数の場合、その変数に対して参照/代入しているコードが追えなくなったり、1か所の変更が他所に影響してしまう可能性が出てきます。

変数がエディタのスクロール範囲内(見える位置)で定義されていればクロージャでよいと思いますし、変数を即時関数の引数に渡す方法もあります。

**値を参照したいとき**

[code]

    // クロージャ
    var a = 1;
    (function() {
      console.log(a); //1
    })();
    
    // どこかで定義されている変数(location.href)を引数に渡して参照
    (function(href) {
      console.log(href);
    })(location.href);
    
[/code]

**値を代入したいとき (値を返す)**

[code]

    var a =
      (function() {
        return 1;
      })();
    console.log(a); // 1
    
[/code]

* * *

> ブラウザ以外  
>  ・一.はブラウザ以外でもaがグローバル変数になるので、一の方が良い？

`a`がスコープ内で未定義であればグローバルの`a`(`global.a`など)が参照され、別の`a`が定義されていればそちらが参照されるかと思います。

ただし、宣言していない変数は、変数に代入するコードを実行するまで存在しないため、参照するとエラーになります。

[code]

    console.log(a);                // ReferenceError をスローします。
    console.log('still going...'); // 実行されません。
    
[/code]

[code]

    var a;
    console.log(a);                // ブラウザによって "undefined" または "" を出力
    console.log('still going...'); // "still going..." と出力
    
[/code]

[code]

    console.log(window.a);         // ブラウザによって "undefined" または "" を出力
    console.log('still going...'); // 実行されません。
    
[/code]

[code]

    // 変数を宣言していない場合、代入時に初めてグローバル変数が作成されます
    a = 1;
    console.log(a);                // 1
    console.log(window.a);         // 1
    
[/code]

変数はスコープにかかわらず宣言をした方が無難です。

<https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/var>

> これら 3
> つの違いにより、変数宣言に失敗し予期しない結果につながる可能性が高いです。結論として、関数スコープかグローバルスコープかにかかわらず、常に変数を宣言することをお勧めします。

またstrictモードの場合、グローバル変数は作成されず、未定義の変数へのアクセスはエラーとなります。

[code]

    // 代入時にグローバル変数は作成されず、エラーとなる
    (function() {
      "use strict";
      a = 1;        // Uncaught ReferenceError: a is not defined
    })();
    
[/code]

[https://developer.mozilla.org/ja/docs/Web/JavaScript/Strict_mode#ミスからエラーへの変換](https://developer.mozilla.org/ja/docs/Web/JavaScript/Strict_mode#%E3%83%9F%E3%82%B9%E3%81%8B%E3%82%89%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%B8%E3%81%AE%E5%A4%89%E6%8F%9B)

> 第一に strict モードでは、偶発的にグローバル変数を作成できないようにします。

* * *

> ブラウザの場合、同じ意味？  
>  ・普通はどちらを使うとかあるでしょうか？

前述の通り、原則グローバル変数は避ける傾向にあります。

それでもブラウザでグローバル変数を使用する場合、絶対にかぶらないであろう変数名のオブジェクトを最初に宣言して、それにアクセスするケースが多い気がします。  
この場合、`window.`をつけることは稀です。

[code]

    // 絶対にかぶらないと思われるプログラムやサービスの名前のオブジェクト
    var MyObject = {};
    MyObject.a = 1;
    
    function foo() {
      console.log(MyObject.a);
    }
    
    function bar() {
      MyObject.a = 0;
    }
    
[/code]

Node.jsの場合、下記参考リンクのように方法は色々あるようですが、グローバルオブジェクトの汚染は避けるべきです。

expressでapp全体の設定値をroutesで使う(module間で変数を受け渡す)方法いろいろ - すぎゃーんメモ  
<http://d.hatena.ne.jp/sugyan/20120110/1326197416>


CC BY-SA 3.0
2016-06-02T18:27:42.887
25394
2016-06-02T19:12:02.650
2016-06-02T19:12:02.650
3068
3068
25392
answer