变量提升
JavaScript 引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升(hoisting)。
console.log(a); // undefined
var a = 1;
等价于
var a;
console.log(a);
a = 1;
冷知识:let变量也会提升。但是不允许在赋值之前使用。比如:
let a = 1 { a = 2; let a; }
会报错。如果没有提升,a=2
应该将外面的a赋值为2。
函数名提升
同理
f(); // 1
function f() {
console.log(1)
}
但是,如果采用赋值语句定义函数,JavaScript 就会报错。
f(); // Uncaught ReferenceError: fun is not defined
let f = function() {
console.log(1)
}
此时,函数等价于
var f;
f();
f = function () {};
如果同一个函数被多次声明,后面的声明就会覆盖前面的声明。
function f() {
console.log(1);
}
f() // 2
function f() {
console.log(2);
}
f() // 2
如果同时采用function命令和赋值语句声明同一个函数,最后总是采用赋值语句的定义。但是在赋值语句前采用的是function命令。
f() // 2
var f = function () {
console.log('1');
}
f() // 1
function f() {
console.log('2');
}
f() // 1
函数内部的变量提升
函数作用域内部也会产生“变量提升”现象。不管在什么位置命令声明的变量,变量声明都会被提升到函数体的头部。
function foo(x) {
if (x > 100) {
var tmp = x - 100;
}
}
等价于
function foo(x) {
var tmp;
if (x > 100) {
tmp = x - 100;
};
}
注:let声明的变量同上文一样