快捷搜索:  汽车  科技

javascript的var与let的区别(助你深入理解JS变量提升)

javascript的var与let的区别(助你深入理解JS变量提升)这个相当于侦查阶段,警察为嫌疑人成立专案组,并且为嫌疑人打上标签(undefined)。2. Initialization(初始化/赋初值) 阶段——分配一块内存,并且建立和作用域中注册变量的联系。在这一步,变量被自动初始化为undefined。当引擎和变量一起起作用时,他们的生命周期包含以下三个阶段:(下面我用破案举例)1. Declaration(声明) 阶段——在作用域中注册一个变量。这个相当于立案阶段,警察知道有这么个嫌疑人了。

JavaScript中变量提升一般是指在代码执行前将变量声明(var变量)或函数声明(function(){})移动至其作用域最顶层的过程。

常见的声明提升

javascript的var与let的区别(助你深入理解JS变量提升)(1)

常见的声明提升

num变量是在声明(var num)之前被访问的,所以它被赋值为undefined。虽然函数function getPi(){return 3.14;}是被定义在最后面,但它是可以在声明的前面被调用的,所以被提升到了作用域的最顶层。这两个是最常规的生命提升的例子。

通过前面的文章 《浅谈JS中变量提升——三分钟让你真正明白变量提升的含义》,我们已经知道了声明提升这回事,但是,其原理是什么呢?

变量的生命周期

当引擎和变量一起起作用时,他们的生命周期包含以下三个阶段:(下面我用破案举例)

1. Declaration(声明) 阶段——在作用域中注册一个变量。

这个相当于立案阶段,警察知道有这么个嫌疑人了。

2. Initialization(初始化/赋初值) 阶段——分配一块内存,并且建立和作用域中注册变量的联系。在这一步,变量被自动初始化为undefined。

这个相当于侦查阶段,警察为嫌疑人成立专案组,并且为嫌疑人打上标签(undefined)。

3. Assignment(分配) 阶段——赋值给已经初始化的变量。

破案成功,成功抓获嫌疑人,知道了嫌疑人的身份和各种信息。

注:警察——引擎,嫌疑人——变量。

javascript的var与let的区别(助你深入理解JS变量提升)(2)

变量的生命周期

注意,变量生命周期中的声明阶段和我们通常所说的变量声明是不同的。简单来说,引擎处理变量声明需要经历三个步骤:注册,初始化,赋值。

var变量的生命周期

javascript的var与let的区别(助你深入理解JS变量提升)(3)

var变量的生命周期

假如有一个里面包含var variable声明的函数作用域开始执行,在函数作用域中的任一声明执行之前里面的变量会在作用域的最顶层注册后立刻初始化。

函数作用域中的变量的声明位置不影响它的注册和初始化阶段。

在注册和初始化之后赋值之前,变量值为undefined并且可以被引用。

在赋值阶段,变量接受了来自它的初始值。

在这个想象的场景中,变量在函数作用域的最顶层被注册和初始化,这样符合严格的变量提升概念————在注册和初始化阶段是没有停顿的。

下面这个例子创建了一个包含var变量的函数作用域:

javascript的var与let的区别(助你深入理解JS变量提升)(4)

函数声明的生命周期

javascript的var与let的区别(助你深入理解JS变量提升)(5)

可以看出,在闭合的函数作用域中,注册/初始化和赋值这三个阶段仅仅用了一步就一次性全部执行完毕,函数已经不依赖于声明它的位置了,它可以在作用域的任何地方被调用。

let变量的生命周期

let变量的处理不同于var变量,主要区别是它的注册和声明是分开进行的。

javascript的var与let的区别(助你深入理解JS变量提升)(6)

let变量的生命周期

let变量在声明之前调用时会报错的。例:

javascript的var与let的区别(助你深入理解JS变量提升)(7)

const和class方式除了只能赋值一次外,生命周期和let变量相同。

为什么变量提升用在let上是无效的呢?

如上所提,声明提升是变量在作用域顶层处注册和初始化耦合的结果。然而let的注册和初始化阶段是解耦的,这就使得声明提升对let无效。这种解耦造成了变量无法被引用的时间死区。

总结

随意的使用var声明变量是很容易导致错误的,基于此,ES2015引入了let。它是会计作用域,使用改良的算法来声明变量。

正是因为注册和初始化的解耦,声明提升才对let无效。在初始化之前,变量处于时间死区且无法被引用。

以下建议可以让你优雅的使用变量声明:

1.先注册,再初始化,然后使用变量,这个流程是正确的并且容易遵循。

2.尽可能的隐藏变量,越少的变量暴露,你的代码就越趋向于模块化。

参考:https://dmitripavlutin.com/7-tips-to-handle-undefined-in-javascript/

编程是一种修行,我愿与志同道合的朋友携手前行,一起探索有关编程的奥妙!

如果您在前端学习的过程中遇到难题,欢迎【关注】并【私信】我,大家一起交流解决!

猜您喜欢: