2015-10-18 25 views
69

letconstの値が宣言される前にアクセスすると、という一時的なデッドゾーンと呼ばれるものがあるため、ReferenceErrorが発生する可能性があると聞いています。時間的不感帯とは何ですか?

一時的なデッドゾーンとはどのようなものですか?スコープとホイストにはどのような関係がありますか?どのような状況で発生しますか?

+4

[letまたはconstで宣言された変数はES6で吊り上げられないのですか?](http://stackoverflow.com/q/31219420/1048572) - 質問はTDZに焦点を当てていませんが、答えは基本的に同じ – Bergi

答えて

101

letconstvarから二つの広い違いがあります:彼らはblock scopedある

  1. を。
  2. 宣言される前にvarにアクセスすると、結果はundefinedになります。それが宣言される前にletconstにアクセスするReferenceErrorをスロー:

console.log(aVar); // undefined 
 
console.log(aLet); // causes ReferenceError: aLet is not defined 
 
var aVar = 1; 
 
let aLet = 2;

(同じように動作し、const、)let宣言はhoistedではないかもしれないことをこれらの例から現れ、 aLetは値が割り当てられる前に存在していないように見えます。

場合ではない、however- letconstは(等varclass及びfunction)掲揚が、範囲を入力し、それらにアクセスすることができない場合宣言されるまでの期間が存在しています。 この期間は、時間的不感帯(TDZ)です。

//console.log(aLet) // would throw ReferenceError 
 

 
let aLet; 
 
console.log(aLet); // undefined 
 
aLet = 10; 
 
console.log(aLet); // 10

この例では、letが掲揚されていることを示しています:

let x = 'outer value'; 
 
(function() { 
 
    // start TDZ for x 
 
    console.log(x); 
 
    let x = 'inner value'; // declaration ends TDZ for x 
 
}());
をはなく、 宣言割り当てられている場合

TDZを終了しますまだReferenceErrorの原因となる内側のスコープでxへのアクセス

Credit: Temporal Dead Zone (TDZ) demystified

letが吊り上げられていない場合は、outer valueと記録されます。

TDZは、バグを強調表示するのに役立ちます。これは、値が宣言される前に値にアクセスすることはめったに意図的ではないためです。

TDZはデフォルトの関数引数にも適用されます。引数は左から右へ、そしてそれが割り当てられるまで各引数はTDZである評価されます。

// b is in TDZ until its value is assigned 
function testDefaults(a=b, b) { } 
testDefaults(undefined, 1); // throws ReferenceError because the evaluation of a reads b before it has been evaluated. 

TDZはbabel.js transpilerではデフォルトで有効になっていません。 REPLで使用するには、「高コンプライアンス」モードをオンにします。 CLIまたはライブラリとして使用するには、es6.spec.blockScopingフラグを指定してください。

続きを読む推奨:TDZ demystifiedおよびES6 Let, Const and the “Temporal Dead Zone” (TDZ) in Depth

+0

'bは定義されていません '(最初のコードスニペットのコメントとして)、しかし、私はあなたがその間に変数名を変更したと思う(そしてあなたはそれについて後で書きます) – oliverpool

+3

また興味深い:[なぜですか一時的なデッドゾーン](http://www.2ality.com/2015/10/why-tdz.html) – zeroflagL

+0

@zeroflagLいいリンク、ありがとう。また、「fooは宣言されていません。初期化されていません」という文言は、上記の答えで明確にする/修正するのに役立ちます。ブロック内で 'let foo'を呼び出すと、そのブロックの先頭に揚げられ宣言されます。 'let foo'の行は、それを初期化させます。そして 'foo = xyz'はそれに値を代入します。 – AJP

関連する問題