你不知道的JavaScript-提升

242 阅读1分钟

提升

提升现象的出现,是因为代码在运行前,引擎会先进行编译。这个过程就好像变量和函数声明从它们在代码中出现的位置被“移动”到了最上面。

准则

  1. 只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。
  2. 每个作用域都会进行提升操作。
  3. 函数声明会被提升,但是函数表达式却不会被提升。
  4. 函数声明和变量声明都会被提升,是函数会首先被提升,然后才是变量。
  5. let和const进行的声明不会再块作用域中进行提升。

例子

示例1

console.log(a);
var a = 2;

编译后的结果是:

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

示例2

foo();

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

编译后的结果是:

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

原理参见第2条。

示例3

foo();

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

编译后的结果是:

var foo;

foo(); // 不是ReferenceError,而是TypeError

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

原理参见第三条。

示例4

foo();

var foo;

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

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

编译后的结果是:

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

foo(); // 1

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

原理见第4条,函数被提升,然后重复声明的变量忽略。但如果重复声明的是函数,则发生覆盖操作,如下:

foo(); // 3

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

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

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

编译后的结果是:

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

foo(); // 3

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