3

スコープに基づいたJavaScriptの変数シャドウイングを理解するのに苦労しています。この小さなコードフラグメントを考えてみましょう。

var k = {
    prop1: 'test',
    prop2: 'anotherTest'
}

for(var k = 0; k < 10; k++) {
    console.log(k);
}

//prints number
console.log(typeof k);

//prints 10
console.log(k);

//undefined
console.log(k.prop1);

これは問題ありません。これは、即時関数スコープのために、ループカウンター変数kが先にデクレートしたjson変数kをシャドウするためです。したがって、json変数kは、いわばアクセスできなくなります。

質問:


  1. メモリ割り当てに関して、元のjson var kにアクセスする方法がなくなったので、ガベージコレクションの対象になりますか?割り当てられたメモリは解放されますか?または、「reference-孤立した」変数はまだ存続していますか?はいの場合、なぜ、どのくらいの期間ですか?

  2. forループの前にコードを記述せずに元のjsonvarkにアクセスする方法はありますか?

次に、わずかに変更された別のコードフラグメントについて考えます。

var k = {
    prop1: 'test',
    prop2: 'anotherTest'
}

var m = {
    prop1: k
}

for(var k = 0; k < 11; k++) {
    console.log(k);
}

//prints number
console.log(typeof k);

//prints 10
console.log(k);

//undefined
console.log(k.prop1);

//reference altered? No, this reference points to the original json k
//firebug dumps object to console
console.log(m.prop1);

質問:


  1. 今回は、別のjsonオブジェクトで、元のkへの参照を事前に保持します。そして確かに、メモリは割り当て解除されません。しかし、m.prop1を評価すると、値が10の更新された整数kに解決されませんか?この解像度が値10のループカウンターにつながっていないのはなぜですか?
4

1 に答える 1

3

1# メモリ割り当ての観点から、元の json var k にアクセスする方法がなくなったので、ガベージ コレクションの対象になりますか? 割り当てられたメモリは解放されますか? または、「参照孤立」変数はまだ生きていますか? はいの場合、なぜ、どのくらいの期間ですか?

と呼ばれる変数は1 つだけですk。他の言語の意味で「変数var を宣言」しません。ここにはシャドーイングはありません。むしろ、関数の先頭に持ち上げられた注釈です。

によって以前に認識されていたオブジェクトkは、もはや強力に到達可能ではないため、再利用できます。(正確な時期は実装に依存しますが、適格です。)

2# for ループの前にコードを書かずに元の json 変数 k にアクセスする方法はありますか?

と呼ばれる変数は1 つだけですk。他の言語の意味で「変数var を宣言」しません。ここにはシャドーイングはありません。むしろ、関数の先頭に持ち上げられた注釈です。

ループ内の代入は、同じ k変数を上書きします。

3# 今回は、別の json オブジェクトで、元の k への参照を事前に保持します。確かに、メモリは割り当て解除されません。しかし、m.prop1 を評価すると、値が 10 の更新された整数 k に解決されませんか? この解決策でループ カウンターの値が 10 にならないのはなぜですか?

変数はオブジェクトではありません。変数名を含む式は、JavaScript で熱心に評価されます。評価されたときに変数によって名前が付けられたオブジェクトは、現在では によって名前が付けられています。したがって、変数に新しい値を割り当てても、以前に評価されたものには影響しません。km = { prop1: k }m.prop1 kk

JavaScript の変数への参照は、代入の左側、または や などの演算子への参照のみtypeofですdel。それ以外の場合、変数は式の生成で参照されることはありません。参照をCall-By-Object-Sharingまたは「オブジェクト変更」セマンティクスと混同しないでください。オブジェクトのプロパティを変更すると、そのオブジェクトが変更されます。(ご覧のとおり、一部の型number不変であり、カスタム プロパティを「固定」できません。)


上記は、コードが関数に表示されることを前提としています。の規則varは、関数の外にある場合は少し異なります。その場合、ローカル変数を宣言せ、グローバルプロパティkを参照するだけです。window.k

1正しい用語「宣言」です。xただし、それは関数全体の属性であり、ステートメントの意味で「評価」されないため、注釈と考える方が明確です。たとえば、次の関数はどちらも同等です。

function () { var x = 1; return x }
function () { x = 1; return x; var x }

以下も参照してください。

于 2012-06-20T05:46:56.783 に答える