9

次のコードについて考えてみます。

<html><head></head>
<body>
    <script type="text/javascript">
        var outside_scope = "outside scope";
        function f1() {
            alert(outside_scope) ;
        }
        f1();
    </script>
</body>
</html> 

このコードの出力は、アラートボックスに「スコープ外」というメッセージが表示されることです。しかし、コードを次のように少し変更すると、次のようになります。

<html><head></head>
<body>
    <script type="text/javascript">
        var outside_scope = "outside scope";
        function f1() {
            alert(outside_scope) ;
            var outside_scope = "inside scope";
        }
        f1();
    </script>
</body>
</html> 

警告ボックスに「未定義」というメッセージが表示されます。どちらの場合も「未定義」と表示されていれば、ロジックを理解できたはずです。しかし、それは起こっていません。2番目の場合にのみ「未定義」と表示されます。どうしてこれなの?

よろしくお願いします!

4

6 に答える 6

21

変数は巻き上げの対象となります。これは、変数が関数内のどこに配置されているかに関係なく、変数が定義されているスコープの先頭に移動されることを意味します。

例えば:

var outside_scope = "outside scope";
function f1() {
    alert(outside_scope) ;
    var outside_scope = "inside scope";
}
f1();

次のように解釈されます。

var outside_scope = "outside scope";
function f1() {
    var outside_scope; // is undefined
    alert(outside_scope) ;
    outside_scope = "inside scope";
}
f1();

そのため、JavaScriptが持つ関数のみのスコープは、関数の先頭ですべての変数を宣言して、何が起こるかを似せることをお勧めします。

于 2009-10-06T22:09:06.410 に答える
12

最初のケースでは、コードは「スコープ外」に初期化されたグローバル変数「outside_scope」にアクセスしています。

Javascriptには関数レベルのスコープがあるため、2番目のケースでは、関数スコープの変数「outside_scope」にアクセスしていますが、アラートボックスの時点ではまだ初期化されていません。したがって、未定義で表示されます。

于 2009-10-06T22:02:23.990 に答える
5

JavaScriptには、ブロックスコープではなく関数スコープがあります。

2番目のケースでは、outside_scopeの宣言が関数の先頭まで引き上げられます(ただし、割り当ては引き上げられません)。

これは、すべての変数宣言を関数の先頭に配置すると、JavaScriptコードが読みやすくなる理由の良い例です。2番目の例は次と同等です。

function f1() {
    var outside_scope;
    alert(outside_scope);
    outside_scope = "inside scope";
}

そして、おそらく「未定義」になっている理由を理解できるでしょう。

于 2009-10-06T22:07:05.807 に答える
4

2番目の例では、ローカル変数は関数スコープ全体に存在します。アラートの後に定義したかどうかは関係ありません。関数全体に存在します。

ただし、実際の割り当てはアラートが発生するまで発生しないため、「未定義」になります。

于 2009-10-06T22:04:32.130 に答える
2

これは、変数宣言の巻き上げと呼ばれるものが原因です。

基本的に、JavaScriptは変数宣言を2つに分割し、宣言を行った場所に割り当てを残し、実際の宣言を関数の先頭に持ち上げます。

var f1 = function ()  {
   // some code
   var counter = 0;
   // some more code
}

var f2 = function () {
   var counter; // initialized with undefined
   // some code
   counter = 0;
   // some more code
}

実行時に、f1()に変換されf2()ます。これについての詳細なブログ投稿をここに書きました。これがコードで何が起こっているのかを理解するのに役立つことを願っています。

これも理由です。JavaScriptの関数の先頭で変数を宣言することをお勧めします。コードが実行されたときに、コードが何をするかを理解するのに役立ちます。

于 2010-05-24T12:10:03.333 に答える
1

それは興味深いケースです。

最初の例では、「グローバル」変数を定義しました。グローバルスコープを持っているため、実行のために任意の関数/オブジェクトでアクセスできます。

2番目の例では、関数スコープ変数を使用してグローバル変数を「ブロック」しましたが、アラートの時点ではまだ初期化されていないため、「未定義」を返します。

これが最も直感的な癖ではないことに同意しますが、それは理にかなっています。

于 2009-10-06T22:04:50.230 に答える