为什么会出现暂时性死区?

  先来看看 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 functionblock 作用域)进行实例化时,在此作用域中用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规定暂时性死区和letconst语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在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声明的才会提升,隐式的全局变量是不会提升的,这样就会存在死区。

最新文章

  1. 第六次团队作业——Alpha冲刺之事后诸葛亮
  2. hp-pa安装oracle和bash
  3. 判断一个 int 向量里是否有相同的数(1)
  4. 移动端调试工具DebugGap推荐。
  5. 维克里拍卖 Vickrey auction
  6. 利用ajaxfileupload.js异步上传文件
  7. Redis(7)Creating and Using Cluster Mode
  8. Android之Handler用法总结
  9. jQuery Mobile里xxx怎么用呀?(集成篇)
  10. Linux查看用户和组命令
  11. UBUNTU下FPT工具--lftp使用说明
  12. IBM之MQ使用指南
  13. [转]在 Mac OS X上编译 libimobiledevice 的方法
  14. css文本样式及控制文本的大小写
  15. JVM菜鸟进阶高手之路五
  16. Error running second Activity: The activity must be exported or contain an intent-filter
  17. GitHub 近 100,000 程序员“起义”:向“996”开炮!
  18. PL/SQL如何调试sql语句、存储过程
  19. db2 runstats和reorg
  20. JS里面的懒加载(lazyload)

热门文章

  1. 应用中有多个Spring Property PlaceHolder导致@Value只能获取到默认值
  2. 多次执行echarts时出现 there is a chart instance already initialized on the dom
  3. ELK学习笔记之logstash的各个场景应用(配置文件均已实践过)
  4. Windows7平台下gitblit服务器安装
  5. 【面试突击】- sql语句的优化分析
  6. 如何将一个react组件进行静态化调用
  7. kube-controller-manager日志报watch of *v1beta1.Event ended with: The resourceVersion for the provided watch is too old
  8. Google 浏览器保存mht网页文件(单个网页)的方法(无需插件)
  9. 原创:基于visual studio 2010 对话框程序的创建
  10. 原生php phpmailer 发送邮件 email