転送とTDZ


ハウスティンとは何ですか。


すなわち、変数と関数のメモリ領域を宣言する前に、予め割り当てられる.
簡単に言えば、コードを順次実行する前に、変数と関数宣言部分をscopeの最上位レベルに昇格させることです.
💡 実際,コードはスキャンの最上位に移動するのではなく,JavaScriptの解析器によって内部処理される.
    console.log(foo); // undefined

    var foo = 123;
    console.log(foo); // 123

狙いを定める


コード作成は、JavaScriptのすべての変数と関数宣言で行われます.
しかし、TDZの影響を受ける構文はエスケープされないように見える可能性があります.次のコードは例を示しています.(以下、TDZの説明)
    console.log(foo); // Uncaught ReferenceError: foo is not defined

    const foo = 123;

TDZとは?


TDZ(Temporal Dead Zone)は直訳して「一時的な死角」とし、スコフの起点から初期化起点までの区間を指す.

変数宣言の手順3


Javascriptでは、変数は宣言、初期化、割り当ての3段階で生成され、次のlet変数のライフサイクルを表示することでTDZをより容易に理解できます.

  • 宣言フェーズ
    実行コンテキストの変数オブジェクトに変数を登録するには.この変数オブジェクトはscope参照のオブジェクトになります.

  • 初期化フェーズ
    実行コンテキストに存在する変数オブジェクトで宣言ステップの変数のメモリを作成するには.このステップで割り当てられたメモリは未定義に初期化されます.

  • 割当フェーズ
    ユーザがundefinedに初期化されたメモリに異なる値を割り当てるには.
  • let変数のライフサイクル



    let変数は呼び出し時に宣言ステップのみを実行し、初期化ステップはコード実行時に発生します.
    したがって、let変数を初期化する前に参照しようとすると、メモリが割り当てられていないため、参照エラーが発生します.
    console.log(foo); // Uncaught ReferenceError: foo is not defined
    
    let foo = 123;

    TDZの影響を受ける構文


    varのような構文は呼び出し時に宣言フェーズと初期化フェーズを同時に実行するので,TDZの影響を受けずに使用できる.宣言フェーズと初期化フェーズは別々に実行されます.つまり、TDZの影響を受ける構文は次のとおりです.

    let, const

    console.log(foo); // Uncaught ReferenceError: foo is not defined 
    console.log(bar); // Uncaught ReferenceError: bar is not defined 
    let foo;
    const bar = 123;

    関数式


    var、let、constと同じです.(varがundefinedに初期化されたため、「is not a function」エラーが発生しました)
    myFunc(); // Uncaught ReferenceError: myFunc is not defined
    
    const myFunc = () => {
      console.log('call myFunc');
    }

    class

    const myCar = new Car('red'); // Uncaught ReferenceError: Car is not defined 
    
    class Car {
      color = '';
    
    constructor(color) {
      this.color = color;
    }
    }

    コンストラクション関数()内部のsuper()


    親クラスが継承されている場合は、コンストラクション関数でsuper()を呼び出す前にTDZに存在します.
    // Does not work
    class MyCar extends Car {
    	constructor(color, power) {
    		this.power = power;
    		super(color);
    	}
    }
    
    const myCar = new MyCar('red', '300hp'); // Uncaught ReferenceError: Car is not defined 
    
    // work
    class MyCar extends Car {
    	constructor(color, power) {
    		super(color);
    		this.power = power;
    	}
    }
    
    const myCar = new MyCar('blue', '300hp');

    デフォルト関数パラメータ


    基本パラメータは、グローバルスキャンと関数スキャンの間の中間スキャンにあります.従って、TDZ制限が存在する.
    // Does not work
    const a = 2;
    function square(a = a) {
    	return a * a;
    }
    
    square(); // Uncaught ReferenceError: Cannot access 'a' before initialization
    
    // work
    const init = 2;
    function square(a = init) {
    	return a * a;
    }
    
    square();

    TDZの影響を受けない構文


    次の構文は、宣言と初期化の両方にあるため、TDZの影響を受けません.

    var

    console.log(foo); // undefined
    var foo = 123;

    function(関数宣言)


    関数宣言は、関数自体によって起動されます.
    myFunc(); // call myFunc
    function myFunc() {
    	console.log('call myFunc');
    }

    import


    import文もいいです.
    myFunc();
    import { myFunc } from "myModule";