JS-变量提升-进阶-上

252 阅读3分钟

在讲JS变量提升的时候,我们先要了解JS代码运行的逻辑顺序,和一些作用域的概念。这样我们就能很简单地理解什么是变量提升了

JS代码的执行顺序:先编译,后执行

编译阶段

  1. 词法分析,语法分析,生成AST(Abstract Syntax Tree ),将AST转变成可执行代码。也就是说编译阶段的时候,编译阶段的产出就是可执行代码。而这个工作就是编译器的工作
  2. 在生成可执行代码的过程中,编译器还会去做一件事,这就是声明var变量,或者是function
var a;

对于这样一段代码,编译器首先会在当前作用域查找是否已经声明了a变量,如果已经有了a变量,就会忽略该声明;否则会要求作用域在当前作用域的集合中声明一个新的变量

这段描述的结尾似乎很奇怪。似乎声明变量是需要作用域相关代码参与的

  1. 编译结束,生成了可执行的代码。在当前作用域,已经有了a的变量声明,但是值为undefined。

执行阶段

这个阶段的执行的任务就是JS引擎的事了,这个我们放在作用域那块再讲


什么是变量提升

了解了编译阶段的动作之后,了解这个就很简单了

变量提升, 就是在代码编译结束之后,代码执行之前,代码中的变量声明就已经存在于当前的作用域中了

为什么会有变量提升

据说是当是设计语言的时候,时间比较赶,就这样处理了。变量提升会导致一系列的问题,并且编程也不够灵活,所以JavaScript后面又设计除了块作用域。这个我们之后再讲。

哪些东西可以变量提升

  1. var声明的变量
  2. 形如function foo() {}这样的一个声明 这样会导致下面的情况
foo();		//'foo'
console.log(a);		// undefined
bar();		//TypeError

var a = 1;

foo(){
    console.log('foo');
}

var bar = function(){
  console.log('bar')
}

第1行和第2行的执行结果,我们很好理解。

第3行的结果这里要特别说明一下

  • 当代码编译完成之后,当前作用域确实已经存在了bar这个变量,但是bar这个变量的值为undefined
  • bar的赋值操作需要等到代码执行才会去做
  • 也就是说,没有执行赋值操作之前,bar就一直是undefined。而对undefined的变量做函数调用的操作,就会报 TypeError的错误

总结

  1. 代码的执行顺序:先编译后执行
  2. 什么是变量提升:代码真正执行之前,声明的变量就已经存在于作用域中
  3. 哪些东西可以变量提升:形如varfunction foo() {}这样的声明
  4. 下篇更精彩 😁