JSにおけるTDZの理解

4144 ワード

原文のリンク:https://acrens.github.io/2017/01/22/2017-01-22-TDZ/春節が近づいてきました.休みももうすぐ来ます.暇な時にはミニブログを利用して、@ruanyfがTDZに関する問題を提出しました.もちろん、阮大の能力でこれはすべて事ではありません.当時はTDZのことはまだ分かりませんでしたので、TDZとTDZとは何かの問題があるかを把握するために時間がかかりました.
  • 例一
  • コード
  • let y = 1;
    function foo(x = y, y) {
        console.log(x);
    }
    foo();  // ReferenceError: y is not defined
  • 解読
  • 関数にデフォルトのパラメータがある場合、呼び出し方法はパラメータを渡さず、三つの作用領域環境が存在する.
  • グローバルスコープ、パラメータスコープ、関数体スコープ.
  • foo関数を実行すると、パラメータスコープはx=yの後にlet yを定義します.注意:let定義です.だから、let定義変数の作用によってx=yが間違いをすることを知っています.
  • コード翻訳:以上のコードを翻訳した後、下記のコードのセグメントで読むことができます.
    function analysis() {
        "use strict";
        let y = 1;
    
        function foo() {  
            let x = arguments[0] !== (void 0) ? arguments[0] : y;   // y not defined
            let y = arguments[1];
        }
        foo();
    
        return {};
    }
  • ケース2
  • コード
  • let y = 1;
    function foo(x = function(){console.log(y)}, y = 2) {
        x(); // 2
        y = 3;
        x(); // 3
    }
    foo();
    console.log(y); //1
  • 解読
  • 関数にデフォルトのパラメータがある場合、呼び出し方法はパラメータを渡さず、三つの作用領域環境が存在する.
  • グローバルスコープ、パラメータスコープ、関数体スコープ.
  • foo関数を実行すると、xは匿名関数変数として登録され、このとき関数は実行されないので、正常である.その後、y値を2と定義し、x()を呼び出して出力するのは当然変数yの値であり、その後もyの値を修正し続け、x()を呼び出し、yの最新値3を出力する.外部consolie.log(y)を実行すると内部関数変数にアクセスできません.アクセス変数は現在のドメインのy=1の値ですので、1を出力します.
  • コード翻訳:以上のコードを翻訳した後、下記のコードのセグメントで読むことができます.
    function analysis() {
        "use strict";
        let y = 1;
    
        function foo() {  
            let x = arguments[0] !== (void 0) ? arguments[0] : function() {
                console.log(y);
            };
            let y = arguments[1] !== (void 0) ? arguments[1] : 2;
            x(); // 2
            y = 3;
            x();    // 3
        }
        foo();
        console.log(y); // 1
    
        return {};
    }
  • ケース3
  • コード
  • let y = 1;
    function foo(x = function(){console.log(y)}) {
        let y = 3;
        x(); // 1
    }
    foo();
  • 解読
  • 関数にデフォルトのパラメータがある場合、呼び出し方法はパラメータを渡さず、三つの作用領域環境が存在する.
  • グローバルスコープ、パラメータスコープ、関数体スコープ.
  • foo関数を実行すると、xは匿名関数の変数として割り当てられ、パラメータのスコープ内に存在し、let y=3は関数のスコープ内に定義され、パラメータのスコープの内部関数に属します.x()が実行されると関数体の作用域で呼び出されますが、パラメータの作用域で定義されているため、実行環境はパラメータの作用域であり、このときパラメータの作用域ではy変数が定義されておらず、内部関数funBody内部で定義されている変数yにもアクセスできません.ここで上位関数にyが定義されているかどうかを調べます.定義されると、その値が出力されます.したがって、最外層変数yの値1を出力します.
  • コード翻訳:以上のコードを翻訳した後、下記のコードのセグメントで読むことができます.
    function analysis() {
        "use strict";
        let y = 1;
    
        function foo() {  
            let x = arguments[0] !== (void 0) ? arguments[0] : function() {
                console.log(y);
            };
    
            function funBody() {
                let y = 3;
                x();
            }
            funBody();
        }
        foo();
    
        return {};
    }
  • ケース4
  • コード
  • function foo(x = function(){console.log(y)}) {
        let y = 3;
        x(); // // ReferenceError: y is not defined
    }
    foo();
  • 解読
  • 関数にデフォルトのパラメータがある場合、呼び出し方法はパラメータを渡さず、三つの作用領域環境が存在する.
  • グローバルスコープ、パラメータスコープ、関数体スコープ.
  • foo関数を実行すると、xは匿名関数の変数として割り当てられ、パラメータのスコープ内に存在し、let y=3は関数のスコープ内に定義され、パラメータのスコープの内部関数に属します.x()が実行されると関数体の作用域で呼び出されますが、パラメータの作用域で定義されているため、実行環境はパラメータの作用域であり、このときパラメータの作用域ではy変数が定義されておらず、内部関数funBody内部で定義されている変数yにもアクセスできません.ここで上位関数にyが定義されているかどうかを調べます.定義されると、その値が出力されます.さもなくばyを申し込むのは定義されていません.この判例は判例の3つのテストにすぎません.
  • コード翻訳:以上のコードを翻訳した後、下記のコードのセグメントで読むことができます.
    function analysis() {
        "use strict";
        function foo() {  
            let x = arguments[0] !== (void 0) ? arguments[0] : function() {
                console.log(y);
            };
    
            function funBody() {
                let y = 3;
                x();
            }
            funBody();
        }
        foo();
    
        return {};
    }
  • 参照
    以上の核心部分はコード翻訳部分にあります.資料と個人の理解を協力することによって、分かりやすいコードを翻訳します.
  • https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zoneand_errors_with_let;
  • http://dmitrysoshnikov.com/ecmascript/es6-notes-default-values-of-parameters/#tdz-temporal-dead-zone-for-parameters;
  • https://github.com/google/traceur-compiler/issues/1604.