0%

变量提升

提到Javascript是怎么执行代码的,大多数人的印象都是一行一行执行啊.但是Javascript在执行代码时,首先会进行解析,最常见的就是变量提升与函数提升.

接下来我们看个例子:

1
2
3
4
5
console.log(a);

var a = 2;

console.log(a);

如果是一行一行执行的话,第一行输出a的时候,a还未定义,所以代码会报错。

但是运行时发现代码能正确执行,而且第一行输出的是undefined,第三行输出 2;这是为什么呢?

原来我们发现Javascript并不是一行一行分析执行代码,而是一段一段分析,然后再执行。这里的一段一段可以看作是一个作用域。那么Javascript是怎么在分析代码的呢?

变量提升

Javascript在进入到一个作用域时,首先会进行“预解析”,查找变量声明和函数声明,也就是找 var 关键字和 function 关键字,然后将变量声明和函数声明提升到作用域顶端,然后再开始执行代码。分析我们前面的例子:

1
2
3
4
5
console.log(a);

var a = 2;

console.log(a);

首先进行“预解析”,查找变量声明和函数声明,找到 var a,放到作用域顶端,继续查找变量声明和函数声明,发现没有了,然后开始执行代码。相当于以下代码:

1
2
3
4
5
6
7
var a;

console.log(a);

a = 2;

console.log(a);

函数提升

然后再看以下代码:

1
2
3
console.log(a);

function a() {}

首先进行“预解析”,查找变量声明和函数声明,找到 function a() {},放到作用域顶端,继续查找变量声明和函数声明,发现没有了,然后开始执行代码。相当于以下代码:

1
2
3
function a() {}

console.log(a);

变量与函数同名

1
2
3
4
5
6
7
8
9
console.log(a)

var a = 2;

console.log(a)

function a () {};

console.log(a)

首先进行“预解析”,查找变量声明和函数声明,找到 var a,然后找到 function a() {},此时由于函数名与变量名相同,函数声明会覆盖变量声明,因此此时代码相当于:

1
2
3
4
5
6
7
8
9
var a = function () {};

console.log(a)

a = 2;

console.log(a)

console.log(a)

函数表达式

1
2
3
4
5
6
7
console.log(a)

var a = function () { console.log("函数表达式") };

function a () { console.log("函数声明") }

console.log(a)

需要注意的是函数表达式并不会提升,因此以上代码相当于:

1
2
3
4
5
6
7
var a = function () { console.log("函数声明") }

console.log(a)

a = function () { console.log("函数表达式") };

console.log(a)

这里只讨论了较为简单的变量提升问题,当函数作用域镶套时,问题就会变复杂,但是基本分析原理还是一样的。每当进入一个作用域时按照上面的方法进行分析即可。

下一篇文章将从更专业的角度说明了变量提升.