1. ホーム
  2. javascript

[解決済み] var キーワードを使用しない変数宣言

2023-04-26 19:33:10

質問

w3schoolsに書いてあります。

var"を使わずに変数を宣言した場合、その変数は常にGLOBALになります。

関数内でグローバル変数を宣言することは有用でしょうか?イベントハンドラでいくつかのグローバル変数を宣言することは想像できますが、それは何のためにあるのでしょうか?RAMのより良い使用法?

どのように解決するのですか?

いいえ、RAM の利点などありません。

w3schoolsが話しているのは、私が呼んでいるものです。 暗黙のグローバルの恐ろしさ . この関数を考えてみましょう。

function foo() {
    var variable1, variable2;

    variable1 = 5;
    varaible2 = 6;
    return variable1 + variable2;
}

単純に見えますが、これは NaN ではなく 11 のタイプミスのため varaible2 = 6; の行にタイプミスがあるためです。そして、タイプミスされた名前のグローバル変数が作成されます。

function foo() {
    var variable1, variable2;

    variable1 = 5;
    varaible2 = 6;
    return variable1 + variable2;
}
console.log(foo());     // NaN
console.log(varaible2); // 6?!?!?!

これは、この関数が代入する varaible2 (タイプミスに注意してください)、しかし varaible2 はどこにも宣言されていません。JavaScript のスコープチェーンの仕組みにより、これは結局のところ グローバルオブジェクト (これは window としてアクセスできます)。

これはルーズモードJavaScriptの特徴で、完全に宣言されていない識別子への代入はエラーではありません。代わりに、グローバルオブジェクトのプロパティを作成し、グローバルオブジェクトのプロパティはグローバル変数になります。(ES5までは、すべてのグローバルはグローバルオブジェクトのプロパティでした。しかし、ES2015では、グローバルオブジェクトのプロパティではない新しい種類のグローバルが追加されました。グローバルスコープ let , const そして class は新しい種類のグローバルを作成します)。

私の例はタイプミスですが、もちろん、やろうと思えばわざとそうすることも可能です。結局のところ、これは言語の明確に定義された部分なのです。というわけで。

myNewGlobal = 42;

...どこであれ myNewGlobal が宣言されていないところでは、新しいグローバルが作成されます。

しかし、私は決して意図的にそれをしないことを強くお勧めします。それはコードを読みにくくし、保守しにくくし、そしてそのコードはJavaScriptモジュールがより一般的になり普及したときに互換性がなくなります。実行時に関数内からグローバル変数を作成する必要が本当にあるなら (すでに赤旗ですが、正当な理由があります)、明示的に window のプロパティに代入してください (あるいは、あなたの環境でグローバルオブジェクトを参照しているものなら何でも構いません。これは window です)。

window.myNewGlobal = 42;

実際、私はES5の ストリクトモード . ストリクトモードでは、宣言されていない識別子への代入は、黙ってグローバルを作成するのではなく、エラーになります。もしストリクトモードを使っていたら foo の問題を診断するのはもっと簡単だったでしょう。

"use strict"; // Turns on strict mode for this compilation unit

function foo() {
    var variable1, variable2;

    variable1 = 5;
    varaible2 = 6;                 // <=== ReferenceError
    return variable1 + variable2;
}
console.log(foo());


少し余談ですが、一般的に、可能な限りグローバルは避けることをお勧めします。グローバル名前空間は、すでにブラウザー上で非常に散らかっています。ブラウザは DOM 内のすべての要素に対して、グローバルに id を持つほとんどの要素、そして name を持つほとんどの要素に対応し、いくつかの定義済みグローバル (例えば title のような) いくつかの定義済みのグローバルがあり、これらはあなたのコードと簡単に衝突する可能性があります。

その代わりに、自分自身で素敵なスコープ関数を定義し、その中にシンボルを入れてください。

(function() {
    var your, symbols, here, if_they_need, to_be_shared, amongst_functions;

    function doSomething() {
    }

    function doSomethingElse() {
    }
})();

そして、その場合、ストリクトモードを有効にするとよいでしょう。

(function() {
    "use strict";
    var your, symbols, here, if_they_need, to_be_shared, amongst_functions;

    function doSomething() {
    }

    function doSomethingElse() {
    }
})();

...これは、前述のように、未宣言の識別子への代入をエラーにする利点があります (さらに 他の様々な役に立つもの ).

なお、JavaScriptの モジュール (ES2015 で追加されましたが、今になってようやくその道が開かれつつあります) では、デフォルトでストリクトモードが有効になっています。(これは class の定義でも同様です(これも ES2015 の新機能です)。