ES6中let和const如何阻止变量声明提升及防止污染window属性
一、问题
ES6中引入let
和const
来进行块级作用域,这个应该是个使用es6的人都知道。
不过我一直不明白为什么 let
和const
能够实现或者做到块级作用域,而不是变量声明提升
.
插曲 javascript 中,es5中(非严格模式),
var
或者function
只会声明提升 ,因此在声明赋值之前进行typeof value
的时候,还是undefined
.
在看zakas的新书的时候,才真正明白为什么能够实现不进行变量声明提升.
二、解释 (TDZ)
zakas 的新书中使用了 javascript 社区的一个词语:
- 临时死区
ECMASCRIPT标准并没有明确指出TDZ,我特意去查了一下,这个词是社区的,但是标准好像没有明确说是什么东西。
基本的思想是:
javascript 引擎在扫描代码发现变量声明的时候,如果遇到了 var 声明,则自然的将其提升到当前作用域(执行环境)的顶部,但是当遇到let
和const
的时候,会将他们
如果在 let 和 const 声明之前访问变量,则会访问 TDZ 中的变量,会触发运行时错误。
本身 TDZ 中的变量,只有在执行了声明之后,才会从 TDZ 中移出,然后才能正常访问。
三、需要注意的点
有一点比较重要的事,变量提升控制的是当前作用域或者执行环境,因此某个TDZ
也只负责某个执行环境(这里的某个并不是说TDZ有很多)。
一个典型的例子:
console.log(typeof value); // undefined
if(true){
console.log(typeof value); // 抛出错误
const value = 1;
}
上面代码中,能够发现,if外访问 value 不会报错,因为 if 外 typeof value
时变量还没有在TDZ中,所以是undefined。
四、全局作用域的绑定
ES5中,如果在全局中声明了name,则其回自动的挂在window的属性上,而 window 本身也有一个 name 属性,并且浏览器对这个属性的解析是和其他属性不同的。
以下面代码举例:
var name = {
first: "ptbird",
last: "postbird"
},
name2 = {
first: "ptbird",
last: "postbird"
};
console.log(name);
console.log(name2);
理论上两者是一样的,但是实际上在输出的时候会发现两者的不同:
因为 name
是覆盖了window.name
,而对这个属性的解析由于其他属性不一样,因此出现这种情况,所以基本上是不推荐使用name进行全局变量的声明。
在es6中,let 和 const 声明的变量则不会自动的挂在window的属性上。
如下所示:
let name = {
first: "ptbird",
last: "postbird"
};
console.log(name);
console.log(window.name);
一开始我也不明白为什么能够做到这一点,不过 zakas 也有指出,实际上let生命的时候,是创建了一个遮蔽window同名属性的全局变量
.
关键点是 遮蔽
,因此实际上使用 window.name
和 name
现在是两个不同的变量, name 将 widnow.name 给遮蔽了。
所以,在es6的代码中,我基本上都是用const或者是let而很少用var,除非特殊需要才会使用var。
文章版权:Postbird-There I am , in the world more exciting!
本文链接:http://www.ptbird.cn/es6-let-const-variable.html
转载请注明文章原始出处 !