次の js コードが、'undefined' テキストを含む 2 番目のアラート ウィンドウを表示するのではなく、'string1' テキストを含む 2 つのアラート ウィンドウを表示する理由を説明できますか?? 両方の変数が同じスコープで記述されている場合..
var a = 'string1';
alert(a);
var a;
alert(a);
ありがとう
次の js コードが、'undefined' テキストを含む 2 番目のアラート ウィンドウを表示するのではなく、'string1' テキストを含む 2 つのアラート ウィンドウを表示する理由を説明できますか?? 両方の変数が同じスコープで記述されている場合..
var a = 'string1';
alert(a);
var a;
alert(a);
ありがとう
変数宣言 (および関数宣言) は、それらが表示されるスコープの先頭に持ち上げられます。割り当てはその場で行われます。コードは効果的に次のように解釈されます。
var a;
var a;
a = 'string1';
たとえば、if
ステートメント本体内で変数を宣言するとどうなるかを考えてみましょう。
console.log(myVar); //undefined (NOT a reference error)
if (something === somethingElse) {
var myVar = 10;
}
console.log(myVar); //10
JavaScript にはブロック スコープがないため、各スコープ内のすべての宣言はそのスコープの先頭に引き上げられます。宣言されていない変数をログに記録しようとすると、参照エラーが発生します。上記の例は次のように解釈されます。
var myVar; //Declaration is hoisted
console.log(myVar);
if (something === somethingElse) {
myVar = 10; //Assignment still happens here
}
console.log(myVar);
そのため、条件が と評価された場合でもfalse
、myVar
変数には引き続きアクセスできます。これが、JSLintがすべての宣言をそれらが表示されるスコープの先頭に移動するように指示する主な理由です。
もう少し詳しく説明すると、ECMAScript 5 の仕様は次のようになります (太字の強調が追加されています)。
コード内のVariableDeclarationおよびVariableDeclarationNoIn dごとに、ソース テキストの順に実行します。
- dnをdの識別子とします。
- varAlreadyDeclared を、引数としてdnを渡してenv のHasBinding具象メソッドを呼び出した結果とします。
- varAlreadyDeclaredがの場合
false
、
- dnと configurableBindingsを引数として渡して、 env のCreateMutableBinding 具象メソッドを呼び出します。
- 引数としてdn、、およびstrictを渡して、 env のSetMutableBinding 具象メソッドを呼び出します。
undefined
そのため、バインドしようとしている識別子を持つバインドが既に存在する場合、何も起こりません。
これは、JavaScript が変数ホイストと呼ばれる処理を行うためです。実際、JS は次のようになります。
var a; // hoisted -> declared on top
a = 'string1';
alert(a);
alert(a);
JavaScript の仕組みの詳細については、C # の良い習慣が JavaScript の悪い習慣を助長する方法を参照してください。
これは、2 番目var a
が個別の変数宣言ではないためです。JavaScript インタープリターに関する限り、最初のものと同じです。
var
は、「この変数の値をに設定する」ではなく、「この変数をこの関数にスコープする」ことを意味しますundefined
。
変数がすでに関数にスコープされている場合はvar foo
、単なるプレーンと同じことを意味しますfoo