JS中的TDZ理解

原文链接:https://acrens.github.io/2017/01/22/2017-01-22-TDZ/

示例

  • 案例一

    1. 代码

    let y = 1;
    function foo(x = y, y) {
        console.log(x);
    }
    foo();  // ReferenceError: y is not defined
    1. 解读

      • 当函数存在默认参数时,且调用方法不传任何参数,会存在三个作用域环境;

      • 全局作用域、参数作用域、函数体作用域;

      • 当执行 foo 函数时,参数作用域在 x = y 之后才定义 let y,注意:let 定义,所以根据 let 定义变量的作用知道 x = y 肯定会报错;

    2. 代码翻译:将以上代码翻译之后可以按下面代码片段阅读更易于理解

    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 {};
    }
  • 案例二

    1. 代码

    let y = 1;
    function foo(x = function(){console.log(y)}, y = 2) {
        x(); // 2
        y = 3;
        x(); // 3
    }
    foo();
    console.log(y); //1
    1. 解读

      • 当函数存在默认参数时,且调用方法不传任何参数,会存在三个作用域环境;

      • 全局作用域、参数作用域、函数体作用域;

      • 当执行 foo 函数时,x 被申明为匿名函数变量,此时函数并未被执行,所以正常;之后定义 y 值为 2,此时调用 x() 输出的当然是变量 y 的值,之后继续修改 y 的值,再继续调用 x(),输出 y 最新值 3;当执行外部 console.log(y) 时并不能访问内部函数变量,访问的变量是当前域下的 y = 1 的值 1,所以输出 1;

    2. 代码翻译:将以上代码翻译之后可以按下面代码片段阅读更易于理解

    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 {};
    }
  • 案例三

    1. 代码

    let y = 1;
    function foo(x = function(){console.log(y)}) {
        let y = 3;
        x(); // 1
    }
    foo();
    1. 解读

      • 当函数存在默认参数时,且调用方法不传任何参数,会存在三个作用域环境;

      • 全局作用域、参数作用域、函数体作用域;

      • 当执行 foo 函数时,x 被赋值为一个匿名函数的变量,且存在与参数作用域内,let y = 3 会被定义到函数体作用域内,属于参数作用域的内部函数;当 x() 执行时是在函数体作用域定被调用,但是其定义是在参数作用域,所以执行环境是在参数作用域内,此时在参数作用域没有定义 y 变量,也不能访问内部函数 funBody 内部定义的变量 y,此时往上级函数查找是否存在 y 被定义,如果被定义则输出其值,所以输出最外层变量 y 的值 1;

    2. 代码翻译:将以上代码翻译之后可以按下面代码片段阅读更易于理解

    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 {};
    }
  • 案例四

    1. 代码

    function foo(x = function(){console.log(y)}) {
        let y = 3;
        x(); // // ReferenceError: y is not defined
    }
    foo();
    1. 解读

      • 当函数存在默认参数时,且调用方法不传任何参数,会存在三个作用域环境;

      • 全局作用域、参数作用域、函数体作用域;

      • 当执行 foo 函数时,x 被赋值为一个匿名函数的变量,且存在与参数作用域内,let y = 3 会被定义到函数体作用域内,属于参数作用域的内部函数;当 x() 执行时是在函数体作用域定被调用,但是其定义是在参数作用域,所以执行环境是在参数作用域内,此时在参数作用域没有定义 y 变量,也不能访问内部函数 funBody 内部定义的变量 y,此时往上级函数查找是否存在 y 被定义,如果被定义则输出其值,否则报 y 没有被定义错误,此案例只是案例三的一种测试;

    2. 代码翻译:将以上代码翻译之后可以按下面代码片段阅读更易于理解

    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 {};
    }

参考

以上核心部分在代码翻译部分,通过配合一下资料及个人的理解,翻译出通俗易懂的代码:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值