7

次のコードでは:

var greeting = "hi";

function changeGreeting() {
    if (greeting == "hi") {
        var greeting = "hello";
    }

    alert(greeting);
}

changeGreeting();​

...greetingは未定義です。ただし、を削除してこれvarに変更changeGreeting()すると:

function changeGreeting() {
    if (greeting == "hi") {
        greeting = "hello";
    }

    alert(greeting);
}

...さすがに「こんにちは」と出ます。

コードでこのような変数を再宣言することは決してありませんが、なぜこれが起こるのでしょうか?

4

3 に答える 3

27

JavaScript変数には関数スコープがあります。したがって、var greeting関数内に存在すること自体がローカル変数を宣言します。これは、条件greetingで言及された時点では未定義ifです。グローバル変数は関数内に表示されず、ローカル変数によって影が薄くなります。したがって、はif発生せず、への割り当てはhello発生せず、変数は未定義のままです。

2番目の例では、全体でグローバル変数を使用しており、ローカル変数によって影が薄くなることはなく(var greeting関数内にないため)、期待どおりに機能します。

于 2012-11-29T12:44:58.240 に答える
6

それは非常に簡単です: JS はVariable 宣言を現在のスコープの先頭に引き上げますが、もちろん、操作 (代入を含む) は引き上げられません (同じスコープ内で、2 番目のケースの説明を参照してください)。したがって、スニペットは次のように翻訳されます

(function()
{
    var currentSize;//undefined
    if (currentSize == 'hi')//always false
    {
        currentSize = 'hello';//assignment that will never be
    }
    alert(currentSize);//alerts undefined, of course
}());

var を省略すると、スコープ スキャン (グローバル スコープで宣言されている変数のチェック) に進みます。悲しいことに、そうすることで、var の最初の使用のコンテキストが (ブランチ内で) 失われ、代入も巻き上げられます。暗黙のグローバルは次のように変換されます:
ありがたいことに、これは真実ではありません。コンソールでこれを裏付けるように思われるいくつかのことをテストしたため、そうであると思いました。この場合、@amadan は正しいです。グローバル変数を使用しています (greetingこれを投稿したときに誤ってスニペットで呼び出されました)。暗黙のグローバルが実際に何であるかを示すために、以下のコードを残します (修正済み)。JS でスコープ/スコープスキャンを理解するのに役立つことを願っています。

var currentSize = 'hello';
//well, actually implied globals can be deleted, so it's more like
Object.defineProperty(this,'currentSize',{value:undefined,
                                          writable:true,
                                          enumerable:true,
                                          configurable:true});
(function()
{
    if (currentSize == 'hi')//always false
    {//this still doesn't get executed
        currentSize = 'hello';//assignment that will never be
    }
    alert(currentSize);//alerts undefined
}());
于 2012-11-29T12:53:05.690 に答える
-1

最初のコードスニペットでは、存在しないグローバル変数をチェックしています->if条件が渡されません。

javascriptスコープと変数の操作方法についてこれをチェックしてくださいJavascriptgarden-関数スコープ

于 2012-11-29T12:46:52.280 に答える