写点什么

深入理解 JS 中的变量提升

用户头像
Verlime
关注
发布于: 2020 年 07 月 22 日
深入理解 JS 中的变量提升

首先来看一段代码,分析一下输出结果:

foo()
console.log(bar)
var bar = 'bar'
function foo() {
console.log('foo')
}
console.log(baz)
// foo
// undefined
// Uncaught ReferenceError: baz is not defined



从上面的代码可以看出,foo() 在未定义时就进行了调用, 输出了 foo,console.log(bar) 在 bar 声明与赋值之前进行了调用,输出了 undefined, 而 console.log(baz) 访问了一个代码中从未定义的变量,代码报错。



因此,我们可以看出以上 JS 代码并不是按照编写的顺序执行的,而是存在一种机制,似乎是函数和变量的声明被提前了? 是的,没错,这种看起来像是声明被提前的现象就是变量提升。



变量提升

详细来说,变量提升就是指 JS 在执行的过程中,JS 引擎会把变量及函数的声明部分提升到代码开头的行为,变量被提升后,会给变量设置默认值 undefined。



如上面代码中的 var bar = 'bar' ,变量提升后会分为声明和赋值两部分, 即:



var bar = undefined
console.log(bar)
// 赋值的代码位置不变
bar = 'bar'



为什么需要变量提升

那么,为什么要变量提升呢?因为 JS 代码需要先编译,再执行,经过编译后会生成执行上下文和可执行代码。



执行上下文就是 JS 执行一段代码时的运行环境,例如调用一个函数时,需要确定该函数所用到的变量、函数等。并且执行上下文中存在一个变量对象,而该对象中就保存了变量提升的内容。



伪代码如下:

VariableEnvironment:
bar -> undefined,
foo -> reference to function foo(){}



那么可执行代码又是什么呢?JS 引擎生成变量对象后会把剩余的代码编译为字节码作为可执行代码,伪代码描述就是:



foo()
console.log(bar)
bar = 'bar'
console.log(baz)



那么可执行代码执行时,按照顺序一行一行的执行,当遇到变量访问或者函数调用时会到变量对象中查找,以上面代码为例 foo() 输出了 fooconsole.log(bar) 输出了 undefined,而 bar = 'bar' 进行了赋值操作,会覆盖掉 undefined,如果再次访问 bar,那么输出就是 bar 了,最后由于 console.log(baz) 在变量对象中并未找到 baz 的定义,因此会抛出异常。



OK,以上就是关于变量提升的介绍。



Photo by KAL VISUALS on Unsplash

发布于: 2020 年 07 月 22 日阅读数: 46
用户头像

Verlime

关注

一个前端工程师 2018.01.01 加入

每天进步一点点ヽ(•̀ω•́ )ゝ

评论

发布
暂无评论
深入理解 JS 中的变量提升