JS代碼的執行是由瀏覽器中的js解析器來執行的,js解析器執行js代碼的時候,分爲兩個過程分爲預解析過程和代碼執行過程。
1.預解析
直接看代碼👀
console.log(a);// undefined
var a = 10;
function f() {
console.log(b);
var b = 20;
}
f();// undefined
正常理解,JS代碼是順序執行,console.log(a)輸出變量a的時候,a變量並未聲明,此時輸出a應報錯纔對,同理f函數中輸出變量b時b並未聲明,也應該報錯纔對,但實際輸出undefined並未報錯。上面這段代碼和下面這段代碼等同:
var a;
console.log(a);// undefined
a = 10;
function f() {
var b;
console.log(b);
b = 20;
}
f();// undefined
由此可見JS的預解析將變量的聲明進行了提升。其實JS預解析也會將函數的定義進行提示。
f1();// 未報錯,輸出f函數被調用
function f1() {
console.log("f函數被調用");
}
和下面代碼等同:
function f1() {
console.log("f函數被調用");
}
f1();// f函數被調用
2.預解析提升位置
function f() {
console.log(c);// undefined
var c = 30;
}
console.log(c);// 報錯
變量的提升只會在當前的作用域中提升,提前到當前作用域的最上面。函數中的變量只會提升到函數作用域中的的最前面。
函數表達式預解析提升問題:
f();// 報錯
var f = function () {
console.log("匿名函數被調用");
};
//和下面等同
var f;
f();// 報錯
f = function () {
console.log("匿名函數被調用");
};
此時會報錯,f is not a function,這是因爲函數表達式的寫法其實是變量的賦值,不是一個函數的定義,預解析只會提升var f的聲明,而f=funfunction(){…};是變量的賦值不會提升,所以報錯。
你我都在努力!