脚本宝典收集整理的这篇文章主要介绍了JS 中 TDZ 的理解,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
原文链接:https://acrens.github.io/2017/01/22/2017-01-22-TDZ/
春节快到了,假期也快到了,空闲之余刷个微博,看见 @ruanyf 提出了一个问题与 TDZ 有关,但是貌似阮大当时还没有意识到这个问题,多亏一些其他业内同仁提出了与 TDZ 相关;当然,以阮大的能力这都不是事。由于当时我本身也还不知道 TDZ 这一回事没有看懂,所以就花了一些时间去搞清楚什么是 TDZ 及TDZ会带来一些什么问题,本文主要是用于介绍我对 TDZ 的一些理解,如有问题,多谢指出。
示例
-
案例一
代码
let y = 1;
function foo(x = y, y) {
console.log(x);
}
foo(); // ReferenceError: y is not defined
-
解读
代码翻译:将以上代码翻译之后可以按下面代码片段阅读更易于理解
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 {};
}
-
案例二
代码
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;当执行外部 console.log(y) 时并不能访问内部函数变量,访问的变量是当前域下的 y = 1 的值 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 {};
}
-
案例三
代码
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 {};
}
-
案例四
代码
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 没有被定义错误,此案例只是案例三的一种测试;
代码翻译:将以上代码翻译之后可以按下面代码片段阅读更易于理解
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 {};
}
参考
以上核心部分在代码翻译部分,通过配合一下资料及个人的理解,翻译出通俗易懂的代码:
以上是脚本宝典为你收集整理的JS 中 TDZ 的理解全部内容,希望文章能够帮你解决JS 中 TDZ 的理解所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。