1

'with' キーワードを使用すると、Javascript with hoisting と scoping で奇妙な動作が発生するようです。

「with」の使用がタブーと見なされていることは理解していますが、フレームワークの 1 つでこれに遭遇し、対処する必要がありました。しかし、それにもかかわらず、

「with」ブロックがある場合、宣言されているが未定義の変数がwithオブジェクトを使用して解決される理由を誰でも説明できますが、クロージャー変数の場合はそうではありません。

デモを行うには、次のコードの出力を参照してください: http://jsfiddle.net/ftK2Z/1/

var x = 90;

function test1(){
    var address = {
         street: 'Haight',
         aptNum: 2
     };


    with (address){
      alert(aptNum + ":" +  x); // this  outputs 2 : undefined. 
      var aptNum = 100,
      x = 10 ;
    }
}

グーグルクロームで確認しました。

注: 私は JS 巻き上げを理解し、アラートの後に var ステートメントを使用することが問題である理由を理解していますが、私が理解しようとしている主なことは、アラート ステートメントでのスコープ解決中に、「aptNum」と「x」の両方が必要であることです。巻き上げのためにローカルスコープで未定義であるため、「宣言されているが定義されていない」と見なす必要があります。

それでも、aptNum は「2」として出力されます。

4

5 に答える 5

2

withブロック内では、変数aptNumは によってシャドウされaddress.aptNumxローカル変数を参照します (address.xそのようなプロパティは存在しないため、決して ではありません)。

それを考慮して、巻き上げると、コードは次と同等になります。

var x = 90;
function test1(){

    var aptNum; // hoisted
    var x;      // hoisted

    var address = {
        street: 'Haight',
        aptNum: 2
    };

    with (address){

        // any reference to aptNum or street inside the with block
        // is actually referencing address.aptNum and address.street

        alert(aptNum + ":" +  x); // this  outputs 2 : undefined. 
                                  // as expected, because there is no address.x
                                  // and the local x is undefined at this point

        aptNum = 100; // this assigns to address.aptNum
                      // the variable aptNum is shadowed by address.aptNum

        x = 10; // this assigns to the local x inside the function 
                // (again because there is no address.x)
    }
}
于 2013-05-15T23:49:39.390 に答える
1

with の使用は推奨されておらず、ECMAScript 5 strict モードでは禁止されています。推奨される代替方法は、一時変数にアクセスするプロパティを持つオブジェクトを割り当てることです。

グローバル変数を持つのは好きではありません。x がアドレス オブジェクトの範囲外にあるためだと思います。パラメータを関数に渡すことができ、機能します。

var x = 90;
test(x);

例: jsFiddle

JavaScript の詳細

于 2013-05-15T23:40:19.973 に答える
1

フィドルから:

with(address){
    $('#output').text('aptNum : ' + aptNum + ",   x : " + x ); 
    var aptNum = 100,
        x = 10 ;
}

ステートメントxの本体で変数が再宣言されています (前のキーワードを参照)。変数宣言は巻き上げられるため、は一時的にに定義され、値がログに記録された後に最終的に に再定義されます。withvarxundefined10

この更新されたフィドルでは、変数宣言ステートメントを単純な代入ステートメントに変更しましx90http://jsfiddle.net/ftK2Z/3/を参照してください

于 2013-05-15T23:29:12.837 に答える