一時的なデッドゾーンとは何ですか?


150

初期化される前に値にアクセスするletと、一時的なデッドゾーンと呼ばれるものconstが原因で発生する可能性があると聞きました。ReferenceError

一時的なデッドゾーンとは何ですか、それはスコープと巻き上げにどのように関係し、どのような状況で発生しますか?


6
ES6で変数がletまたはconstでホイストされていないのと重複する可能性はありますか?-質問はTDZに焦点を当てていませんが、答えは基本的に同じである
Bergi

回答:


201

letconst2つの大きな違いがありvarます。

  1. それらはブロックスコープです。
  2. var宣言される前にアクセスすると、結果が得られundefinedます。宣言される前、letまたはconst宣言される前にthrows ReferenceError

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

これらの例から、let宣言(およびconst、同じように機能する)は、値が割り当てられる前は存在していないように見えるため、巻き上げられない可能性があるようにaLet見えます。

すなわち、however-そうではないletconst されて掲揚(同様にvarclassfunction)が、スコープを入力し、それらにアクセスすることができない場合宣言されるまでの期間があります。この期間は、一時的なデッドゾーン(TDZ)です。

TDZは次のときに終了しaLetますは、割り当てられるのではなく、宣言さ

//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)の詳細

へのアクセス x内部スコープですると、やはりが発生しReferenceErrorます。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トランスパイラーではデフォルトで有効になっていません。「高コンプライアンス」モードをオンにして、REPLで。供給es6.spec.blockScopingCLIまたはライブラリとしてそれを使用するためのフラグを。

さらに読むことをお勧めします:TDZ demystifiedおよびES6 Let、Const、およびDepthの「Temporal Dead Zone」(TDZ)



@zeroflagL良いリンク、ありがとう。また、「fooは宣言されておらず、初期化されていない」とあり、その言語は上記の答えを明確化/修正するのに役立ちます。 let fooブロック内では、ブロックはそのブロックの最上部で持ち上げられて宣言されます。ラインlet fooが初期化されます。そしてfoo = xyz、それに値が割り当てられます。
AJP 2017年

2
これは素晴らしい投稿だと思います!しかし、「レット」は巻き上げの対象ではないという印象を受けましたか?私はこれをMozillaのドキュメントで見つけました:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 私は悪口を言うつもりはありません。興味があるだけで、説明を求められました。
dmarges

1
@jeows MDNページには、まだ巻き上げられていないと書かれています。あなたが言っていることを本当に確信しているなら、あなたはそれを編集しようとするべきです。私はそれについて質問を投稿するべきだと思います。
doubleOrt 2017

1
@joews IMO、それらはホイストされているが、TDZが原因で宣言に到達する前にアクセスできないと言うこともできますし、ホイストされていないとしてもTDZがそれらへの参照によってエラーをスローするようにすることもできます。実際には、両方のステートメントが等しく当てはまります。ただし、「巻き上げ=エンジンがその変数の存在を認識しているときはいつでも」というように、抽象的な意味で「巻き上げ」という用語を使用していると思います。それが理由ですか?さらに、スペックはそれについて何と言っていますか?
doubleOrt 2018

7

巻き上げ:
letconstvarすべての掲揚のプロセスを取得しています。
(何が意味するかというと、それらは上に行き、スコープの上部で宣言します。)

初期化:

  • var 初期プロセスも経て、の初期値を得る undefined
  • 一方letconst最初のプロセスをスローしなかったため、すでに宣言されていますが、それらの値にはアクセスできません。それらを入れたものtemporal dead zone

だからまもなく:

巻上工程:varletconst
初期化プロセス: var


0

letおよびconst変数の場合、基本的に、Temporal Dead Zoneはゾーンです

"変数が宣言される前"、

つまり、これらの変数の値にアクセスできない場合、エラーがスローされます。

let sum = a + 5;        //---------
//some other code       //         | ------>  this is TDZ for variable a
                        //         |
console.log(sum)        //---------
let a = 5;

上記のコードはエラーを出します

変数 'a'にvarを使用しても、同じコードでエラーは発生しません。

var sum = a;                            
console.log(sum)     //prints undefined
var a = 5;

2番目の例では、コンソールログに「NaN」が生成されます(undefinedおよびを追加した結果5)。declaratationvar a掲揚されるが、inifialisationコードsettng a5にはありません。
traktor53

はい、そうです、初期化なしでaが巻き上げられます。したがって、aは未定義になります。
niranjan harpale

引用されている最初の例は正しくありません。修正するか削除してください。
SpidiのWeb
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.