对于变量提升相信大家都很熟悉了,直接上代码演示。
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('去一趟天涯'); }
总结一句话:先编译,再执行。