ES6 中 let 和 const 如何阻止变量声明提升及防止污染 window 属性

发布于 2023-01-08 18:41:03 字数 2185 浏览 90 评论 0

ES6 中 let 是否真正的存在变量提升这一问题,我查阅了相关资料,做出了以下总结。

相信很多人在看 阮一峰 ES6 入门 let 和 const 命名这一章的时候,有说到 let 不存在变量提升,存在暂时性死区这一说法,其实变量的生成有两个阶段,第一个阶段是变量的创建阶段,第二是变量的初始化阶段,而我们常常所说的变量提升恰恰是在初始化阶段,所以存在说法上的不一致,在变量创建的时候是可以被提升的,只不过由于ES6的暂时性死区没有达到真正的提升,导致初始化没有被提升,我们常常说的提升也是指初始化阶段,所以说 ES6 的 let 在初始化阶段是不存在提升这一说的。

临时死区的基本思想:

  1. javascript 引擎在扫描代码发现变量声明的时候,如果遇到了var 声明,则自然的将其提升到当前作用域(执行环境)的顶部,但是当遇到letconst的时候,会将他们放在临时死区中。
  2. 如果在 letconst 声明之前访问变量,则会访问临时性死区中的变量,会触发运行时错误。
  3. 本身临时性死区中的变量,只有在执行了声明之后,才会从临时性死区中移出,然后才能正常访问。
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 中,letconst 声明的变量则不会自动的挂在 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.namename 现在是两个不同的变量,name 将  widnow.name 给遮蔽了。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

文章
评论
27 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文