一. let/const:
1. “暂时性死区”概念:在代码块内,使用let/const
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。“暂时性死区”也意味着typeof
不再是一个百分之百安全的操作。
2. 块作用域与函数声明:
function f() { console.log('I am outside!'); } (function () { if (false) { // 重复声明一次函数f function f() { console.log('I am inside!'); } } f(); }()); // I am inside!
上面代码相当于以下代码:
// ES5 环境 function f() { console.log('I am outside!'); } (function () { function f() { console.log('I am inside!'); } if (false) { } f(); }());
在 ES5 中运行,会得到“I am inside!”,因为在if
内声明的函数f
会被提升到函数头部。ES6 就完全不一样了,理论上会得到“I am outside!”。因为块级作用域内声明的函数类似于let
,对作用域之外没有影响。但是,如果你真的在 ES6 浏览器中运行一下上面的代码,是会报错的。原来,如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。
- 允许在块级作用域内声明函数。
- 函数声明类似于
var
,即会提升到全局作用域或函数作用域的头部。 - 同时,函数声明还会提升到所在的块级作用域的头部。
根据这三条规则,在浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于var
声明的变量。
// 浏览器的 ES6 环境 function f() { console.log('I am outside!'); } (function () { if (false) { // 重复声明一次函数f function f() { console.log('I am inside!'); } } f(); }()); // Uncaught TypeError: f is not a function
上面的代码在符合 ES6 的浏览器中,都会报错,因为实际运行的是下面的代码:
// 浏览器的 ES6 环境 function f() { console.log('I am outside!'); } (function () { var f = undefined; if (false) { function f() { console.log('I am inside!'); } } f(); }()); // Uncaught TypeError: f is not a function