聊聊对浏览器的认知(四):浏览器中的JavaScript:变量提升和执行上下文

168 阅读2分钟

对于变量提升相信大家都很熟悉了,直接上代码演示。

gotianya(); // 可以正常调用
console.log(tianya); // 这里输出undefined
var tianya = "天涯";
function gotianya (){
  console.log('去一趟天涯');
}

按照惯例,先把定义粘过来:所谓的变量提升,是指在 JavaScript 代码执行过程中,JavaScript 引擎把变量的声明部分和函数的声明部分提升到代码开头的“行为”。变量被提升后,会给变量设置默认值,这个默认值就是我们熟悉的 undefined。

变量提升的原因(JavaScript执行流程)

js代码在执行前,是需要被JavaScript 引擎编译的,编译完成之后才会被执行。如果对上面的代码进行分离编译和执行,那么应该是这样的:

// 编译阶段
var tianya = undefined;
function gotianya() {
  console.log('去一趟天涯');
}

// 执行阶段
gotianya(); 
console.log(tianya);
tianya = "天涯";

上面模拟的代码可以看出,变量提升的真面目,是JavaScript 引擎编译后的结果。编译后会生成两部分内容:执行上下文和可执行代码

执行上下文

执行上下文是 JavaScript 执行一段代码时的运行环境。

  • 当 JavaScript 执行全局代码的时候,会编译全局代码并创建全局执行上下文,而且在整个页面的生存周期内,全局执行上下文只有一份。
  • 当调用一个函数的时候,函数体内的代码会被编译,并创建函数执行上下文,一般情况下,函数执行结束之后,创建的函数执行上下文会被销毁。
  • eval() 上下文,不推荐用,忽略。

          _ 图片获取于网络非作者原创_

执行上下文中存在一个变量环境的对象,该对象保存了变量提升的内容,大概可以理解成下面的结构:

tianya -> undefined
gotianya -> function () { console.log('去一趟天涯'); }

在执行阶段,JavaScript引擎会从变量环境中去查找定义的变量和函数,进行赋值和执行。

tianya -> "天涯"
gotianya -> function () { console.log('去一趟天涯'); }

总结一句话:先编译,再执行