JavaScript 内功心法——变量提升及函数提升

前端必备内功之变量提升及函数提升

Posted by Shiyanping on November 5, 2018

1. 变量提升

变量不管在任何地方声明,js 引擎在编译时都会发生变量提升。

例:

1
2
3
console.log(a); // undefined

var a = 2;

在定义变量 a 之前打印 a,并不会报Uncaught ReferenceError: i is not defined的错,而是输出undefined,因为var a = 2会进行变量提升,会被引擎解析成如下代码:

1
2
3
4
5
var a;

console.log(a); // undefined

a = 2;

var a = 2,js 引擎其实会分解成var aa = 2两个单独的声明,第一个是编译阶段,第二个是执行阶段。

再用另外一个例子说明一下变量提升,变量如果在不符合条件的 if 语句中定义,也会发生变量提升。

例:

1
2
3
4
5
6
7
function test() {
  if (false) {
    var i = 100;
  }
  console.log(i); // undefined
}
test();

虽然是在判断条件中定义的变量,并且当前条件也不满足,但是在访问定义的变量时,会提示 undefined,而不是Uncaught ReferenceError: i is not defined报错,充分说明了在判断条件中定义的变量,即时没有执行到判断条件中,变量也会提前声明。

2. 函数提升

函数声明和变量声明一样,在被执行前都会进行“移动”处理,“移动”到各自作用域的最顶端,也就是所谓的提升。

在定义函数之前使用函数,函数也会执行。

例:

1
2
3
4
5
6
test();

function test() {
  var i = 1;
  console.log(i); // 1
}

这种情况在我们开发中会经常遇到,我们有的时候会把函数定义到执行函数的下面,也不会报错,不报错的原因就在于此,函数进行了提升。

虽然函数和变量都会提升,但是函数提升优于变量提升

例:

1
2
3
4
5
6
7
8
9
foo(); // 1

function foo() {
  console.log(1);
}

var foo = function() {
  console.log(2);
};

会输出 1 而不是 2,因为引擎会解析成一下代码:

1
2
3
4
5
6
7
8
9
10
11
function foo() {
  console.log(1);
}

var foo; // 被忽略了

foo(); // 1

foo = function() {
  console.log(2);
};

var foo 是重复声明,所以被忽略了,因为函数声明优于变量声明。

如何区分函数声明和函数表达式:function 关键字出现的位置(不是一行,是整个声明的位置),如果 function 是声明中的第一个词,就是函数声明,否则就是函数表达式。