JS 中的声明提升

通常情况下变量都需要先声明后使用,但是在 js 中如果我们先使用变量再用 var 声明将不会抛异常,但是由于未赋值,该变量将会以 undefined 存在。

Javascript 中,函数及变量的声明都将提升到作用域的顶部。

变量提升

1
2
3
4
5
6
var x1 = 1;
console.log('🚀 ~ x1', x1);

// 不会报错,输出undefined
console.log('🚀 ~ x2', x2);
var x2 = 0;

Javascript 允许先使用变量再用 var 去定义,像上述代码对于 x2 变量相当于:

1
2
3
var x2;
console.log('🚀 ~ x2', x2);
x2 = 0;

可以看出 var 声明会提升,但是变量定义不会提升,上述输出的 x2 为 undefined。

除去 var 声明,javascript 中还有 const 和 let 声明变量,和 var 一样的是声明操作会被提升到代码块顶部,但是在未定义之前使用变量将会抛出 ReferenceError 错误。

1
2
3
4
5
6
7
const x1 = 0;
console.log('🚀 ~ x1', x1);

console.log('🚀 ~ x2', x2); // ReferenceError: Cannot access 'x2' before initialization
const x2 = 0;

console.log('🚀 ~ x3', x3); // ReferenceError: x3 is not defined

函数提升

Javascript 中的函数 function 声明也会被提升至代码块顶部,但是函数表达式不会提升,在定义函数表达式之前不能使用函数表达式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
testFn1(); // testFn1
function testFn1() {
console.log('🚀 ~ testFn1', 'testFn1');
}

testFn2(); // ReferenceError: Cannot access 'testFn2' before initialization
const testFn2 = () => {
console.log('🚀 ~ testFn2', 'testFn2');
};

testFn3(); // TypeError: testFn3 is not a function
var testFn3 = () => {
console.log('🚀 ~ testFn2', 'testFn2');
};

几个 🌰

var 声明是全局作用域或函数作用域,而 let 和 const 是块作用域。var 变量可以在其范围内更新和重新声明,但是 let 只能被更新不能重新声明,const 不能更新也不能重新声明。

结合 var,let 和 const 的特点,具体可以体现在下面两个代码块:

1
2
3
4
5
6
7
8
9
10
// 将两块函数顺序互换输出不变
var test = function () {
console.log(1);
};

function test() {
console.log(2);
}

test(); // 1
1
2
3
4
5
6
7
8
9
const test = function () {
console.log(1);
};

function test() {
console.log(2);
}

test(); // SyntaxError: Identifier 'test' has already been declared