ES6 中 let 和 const 如何阻止变量声明提升及防止污染 window 属性
ES6 中 let 是否真正的存在变量提升这一问题,我查阅了相关资料,做出了以下总结。
相信很多人在看 阮一峰 ES6 入门 let 和 const 命名这一章的时候,有说到 let 不存在变量提升,存在暂时性死区这一说法,其实变量的生成有两个阶段,第一个阶段是变量的创建阶段,第二是变量的初始化阶段,而我们常常所说的变量提升恰恰是在初始化阶段,所以存在说法上的不一致,在变量创建的时候是可以被提升的,只不过由于ES6的暂时性死区没有达到真正的提升,导致初始化没有被提升,我们常常说的提升也是指初始化阶段,所以说 ES6 的 let 在初始化阶段是不存在提升这一说的。
临时死区的基本思想:
javascript
引擎在扫描代码发现变量声明的时候,如果遇到了var
声明,则自然的将其提升到当前作用域(执行环境)的顶部,但是当遇到let
和const
的时候,会将他们放在临时死区中。- 如果在
let
和const
声明之前访问变量,则会访问临时性死区中的变量,会触发运行时错误。 - 本身临时性死区中的变量,只有在执行了声明之后,才会从临时性死区中移出,然后才能正常访问。
console.log(typeof value); // undefined
if(true){
console.log(typeof value); // 抛出错误 Uncaught ReferenceError: Cannot access 'value' before initialization
const value = 1;
}
上面代码中,能够发现,if 外访问 value 不会报错,因为 if 外 typeof value 时变量还没有在临时性死区中,所以是 undefined。ES5 中,如果在全局中声明了 name,则其回自动的挂在 window 的属性上,而 window 本身也有一个 name 属性,并且浏览器对这个属性的解析是和其他属性不同的。
以下面代码举例:
var name = {
first: "ptbird",
last: "postbird"
},
name2 = {
first: "ptbird",
last: "postbird"
};
console.log(name);
console.log(name2);
理论上两者是一样的,但是实际上在输出的时候会发现两者的不同:
[object Object]
{first:"ptbird",last:"postbird"}
因为name
是覆盖了 window.name
,而对这个属性的解析由于其他属性不一样,因此出现这种情况,所以基本上是不推荐使用 name
进行全局变量的声明。在 ES6 中,let
和 const
声明的变量则不会自动的挂在 window
的属性上。
let name = {
first: "ptbird",
last: "postbird"
};
name2 = {
first: "geek",
last: "james"
}
console.log(name);
console.log(window.name);
console.log(name2);
输出结果:
{first:"ptbird",last:"postbird"}
[object Object]
{first: "geek", last: "james"}
实际上 let 声明的时候,是创建了一个遮蔽 window
同名属性的全局变量,关键点是 遮蔽,因此实际上使用 window.name
和name
现在是两个不同的变量,name
将 widnow.name
给遮蔽了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: Vue 基础指令
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论