暂时性死区TDZ理解与总结
为什么会出现暂时性死区?
先来看看 ES6 标准中对 let/const
声明中的解释 第13章,有如下一段文字:The variables are created when their containing Lexical Environment is instantiated but may not be accessed inany way until the variable’s LexicalBinding is evaluated.
当然这段话我看完也很懵,查阅了一些帖子,翻译成人话就是:
当程序的控制流程在新的作用域(module
function
或 block
作用域)进行实例化时,在此作用域中用let/const声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。
如果你还是记不住,那么只需理解下面这句话即可:
ES6规定,let/const
命令会使区块形成封闭的作用域。若在声明之前使用变量,就会报错。总之,在代码块内,使用 let
命令声明变量之前,该变量都是不可用的。这在语法上,称为 “暂时性死区”( temporal dead zone,简称 TDZ)。
if (true) {
// TDZ开始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError let tmp; // TDZ结束
console.log(tmp); // undefined tmp = ;
console.log(tmp); //
}
上面代码中,在let
命令声明变量tmp
之前,都属于变量tmp
的“死区”。“暂时性死区”也意味着typeof
不再是一个百分之百安全的操作。
typeof x; // ReferenceError
let x;
上面代码中,变量x
使用let
命令声明,所以在声明之前,都属于x
的“死区”,只要用到该变量就会报错。因此,typeof
运行时就会抛出一个ReferenceError
。大家应该养成良好的编程习惯,变量一定要在声明之后使用,否则就报错。
有些“死区”比较隐蔽,不太容易发现。
function bar(x = y, y = ) {
return [x, y];
} bar(); // 报错
上面代码中,调用bar
函数之所以报错,是因为参数x
默认值等于另一个参数y
,而此时y
还没有声明,属于”死区“。如果y
的默认值是x
,就不会报错,因为此时x
已经声明了。
ES6规定暂时性死区和let
、const
语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在ES5是很常见的,现在有了这种规定,避免此类错误就很容易了。
总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
我们再来看一个问题
function bar() {
var x = y
y =
return [x, y];
} bar() // y未定义
function bar() {
var x =
y =
return [x, y];
}
bar()
window.y //
至于上面的y未定义的错,也是一个死区。千万不要以为下面隐式声明的一个全局变量就以为y会变量提升,不是这样的。只有var声明的才会提升,隐式的全局变量是不会提升的,这样就会存在死区。
最新文章
- 第六次团队作业——Alpha冲刺之事后诸葛亮
- hp-pa安装oracle和bash
- 判断一个 int 向量里是否有相同的数(1)
- 移动端调试工具DebugGap推荐。
- 维克里拍卖 Vickrey auction
- 利用ajaxfileupload.js异步上传文件
- Redis(7)Creating and Using Cluster Mode
- Android之Handler用法总结
- jQuery Mobile里xxx怎么用呀?(集成篇)
- Linux查看用户和组命令
- UBUNTU下FPT工具--lftp使用说明
- IBM之MQ使用指南
- [转]在 Mac OS X上编译 libimobiledevice 的方法
- css文本样式及控制文本的大小写
- JVM菜鸟进阶高手之路五
- Error running second Activity: The activity must be exported or contain an intent-filter
- GitHub 近 100,000 程序员“起义”:向“996”开炮!
- PL/SQL如何调试sql语句、存储过程
- db2 runstats和reorg
- JS里面的懒加载(lazyload)
热门文章
- 应用中有多个Spring Property PlaceHolder导致@Value只能获取到默认值
- 多次执行echarts时出现 there is a chart instance already initialized on the dom
- ELK学习笔记之logstash的各个场景应用(配置文件均已实践过)
- Windows7平台下gitblit服务器安装
- 【面试突击】- sql语句的优化分析
- 如何将一个react组件进行静态化调用
- kube-controller-manager日志报watch of *v1beta1.Event ended with: The resourceVersion for the provided watch is too old
- Google 浏览器保存mht网页文件(单个网页)的方法(无需插件)
- 原创:基于visual studio 2010 对话框程序的创建
- 原生php phpmailer 发送邮件 email