4

次の2つのJavaScriptスニペットについて考えてみます。

var x = 2;
function f() {
    var y = x;
    eval('var x;');
    return y;
}

対。

var x = 2;
function f() {
    var y = x;
    var x;
    return y;
}

唯一の違いは、私がに置き換えeval('var x;');たことvar x;です。

最初のものはを返します2が、2番目のものはを返しますundefined。なんで?

4

3 に答える 3

5

変数宣言は、パーサーによって字句スコープの先頭に引き上げられます。コードの2番目のブロックでは、実際に実行される方法は次のとおりです。

function f() {
  var x, y;
  y = x;
  return y;
}

関数宣言も引き上げられます。正味の効果は、変数宣言が常にそれが現れる字句スコープ全体を含むと見なされるべきであるということです。変数が関数内のどこかxで宣言されている場合、その関数内のすべての参照はローカル変数への参照です。var x

最初の例では、このeval()行は単なる正規表現ステートメントであるため、関数に表示された順に実行されます。

于 2012-11-24T20:55:58.470 に答える
1

2つ目では、var他のステートメントが実行される前に、が関数の先頭に引き上げられます*。

つまり、コーディングが次のようになります。

var x = 2;
function f() {
    var x, y
    y = x;
    return y;
}

しかし、最初のものでは、それは表現var xの一部であるeval()ため、2番目のもののように持ち上げられる*機会がありません。


※「吊り上げ」という用語は正式な用語ではありません。これは、実行コンテキスト内で式が評価される前に宣言が行われるという事実を説明するために人々が使用する単なる単語です。関数宣言も引き上げられます。

于 2012-11-24T20:56:27.500 に答える
1

これは、インタプリタが関数のスコープ内にある場合、インタプリタundefined内で宣言されているすべての変数に値を設定するためです(varキーワードのプレフィックスが付いています)。宣言をどこに置いたかは関係ありません。関数内に変数宣言がある場合、変数の値は、そのundefined値を明示的に設定するまで続きます。最初のケースeval('var x;')では、の値が設定されているときにまだ評価されていないものがありますy。これが、の値がでyある理由です。これは、上位スコープ2の変数の値がであるためです。同じことがここにあります:x2

var x = 2;
function foo() {
    var y = x;
    console.log(y); //undefined
    console.log(x); //undefined
    var x = 3;
}

function bar() {
    var y = x;
    console.log(y); //2
}

var x = 2;
function foobar() {
    console.log(x); //undefined
    var x;
    console.log(x); // undefined
    x = 3;
    var y = x;
    console.log(y); //3
}

評価は正規表現と同じように評価されます。

于 2012-11-24T20:57:07.380 に答える