Javacript中的变量提升

我认为在搞清楚变量提升这个问题之前先弄清楚JS引擎执行(下一篇再说吧)这两个东西

JS引擎执行

分为两个阶段:预处理阶段(编译),执行阶段

(1)预处理阶段

一共完成四件事情:(以 var a=10;进行解释)

  • 词法分析:将var a=10;分解为var/a/=/10/;五个代码块
  • 语法分析:将词法单元流(数组)转化成抽象语法树AST(Abstract Syntax Tree)
  • 生成可执行代码:相当于是再把AST转换成浏览器可执行的代码,或者是各种语言引擎可执行的代码。

在编译阶段,会创建变量对象(VO),变量对象中存放所有变量声明(以变量名建立一个属性,undefined为变量值),所有函数声明(在变量对象中以函数名建立一个属性,属性值为指向该函数所在内存地址的引用), 函数的所有形参(如果是在函数上下文中)。
var a=10;相当于变为了:

var a=undefined;//编译阶段

(2)执行阶段
执行阶段,变量对象(VO)变为了活动对象(AO)

未进入执行阶段前,变量对象中的属性都不能访问!但是进入到执行阶段之后,变量对象转变成了活动对象,里面的属性都能被访问了,然后开始进行执行阶段的操作。

var a=10;//执行阶段

提升机制

(1)变量提升
变量提升我理解为:在编译阶段将变量提升到所在域的最开头。

console.log(a);//undefined
var a=10;

在编译阶段,a的值为undefined,所以输出为未知。

(2)函数提升

函数分为表达式函数和声明式函数,只有声明式函数会进行变量提升(将整个函数提到所在域的最开头)。

function myTest(){
    foo();
    function foo(){
        alert("我来自 foo");
    }
}
myTest();//我来自 foo
function myTest(){
    foo();
   var foo =function foo(){
        alert("我来自 foo");
    }
}
myTest();//报错,因为表达式函数不会提升

总结:变量提升也就是在编译阶段,将变量和声明式函数赋了一个默认值,一个是undefined,一个是函数体本身。

注意:还有一个很有意思的例子

var a = 1;
 function foo() {
  if (!a) {
    var a = 2;
  }
  alert(a);
};
 
foo();

我刚开始很纳闷为啥是2,后来想了下:在函数作用域中,变量提升为var a=undefined,if语句中对undefined取非为true,所以会执行if里面的内容。

参考:https://www.jb51.net/article/172608.htm
https://www.cnblogs.com/damonlan/archive/2012/07/01/2553425.html
https://www.cnblogs.com/TomXu/archive/2012/01/16/2309728.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值