這是我參與8月更文挑戰的第10天,活動詳情查看:8月更文挑戰瀏覽器
JavaScript 代碼的執行是由瀏覽器中的 JavaScript 解析器來執行的。JavaScript 解析器執行JavaScript 代碼的時候,分爲兩個過程:預解析過程和代碼執行過程markdown
預解析過程:app
把變量的聲明提高到當前做用域的最前面,只會提高聲明,不會提高賦值。函數
把函數的聲明提高到當前做用域的最前面,只會提高聲明,不會提高調用。post
先提高 var,再提高 function。ui
在預解析過程當中,全部定義的變量,都會將聲明的過程提高到所在的做用域最上面,在未來的代碼執行過程當中,按照前後順序會先執行被提高的聲明變量過程。url
提高過程當中,只提高聲明過程,不提高變量賦值,至關於變量定義未賦值,變量內存儲 undefined 值。spa
所以,在 js 中會出現一種現象,在前面調用後定義的變量,不會報錯,只會使用 undefined 值。3d
在預解析過程當中,全部定義的函數,都會將聲明的過程提高到所在的做用域最上面,在未來的代碼執行過程當中,按照前後順序會先執行被提高的函數聲明過程。code
在預解析以後的代碼執行過程當中,函數定義過程已經在最開始就會執行,一旦函數定義成功,後續就能夠直接調用函數。
所以,在 js 中會出現一種現象,在前面調用後定義的函數,不會報錯,並且能正常執行函數內部的代碼。
函數聲明提高能夠用於調整代碼的順序,將大段的定義過程放到代碼最後,可是不影響代碼執行效果。
console.log(a);
console.log(fun)
function fun(){
console.log(2);
}
var a=1;
console.log(a);
複製代碼
預解析過程當中,先提高 var 變量聲明,再提高 function 函數聲明。
假設出現變量名和函數名相同,那麼後提高的函數名標識符會覆蓋先提高的變量名,那麼在後續代碼中出現調用標識符時,內部是函數的定義過程,而不是 undefined。
若是調用標識符的過程在源代碼函數和變量定義後面,至關於函數名覆蓋了一次變量名,結果在執行到變量賦值時,又被新值覆蓋了函數的值,那麼在後面再次調用標識符,用的就是變量存的新值。
建議:不要書寫相同的標識符給變量名或函數名,避免出現覆蓋。
console.log(fun);
var fun;
function fun(){
console.log(2);
}
console.log(fun); //能夠看到既有變量又有函數時, 最後輸出fun是什麼
fun = "hello"; //字符串不能傳給函數, 因此後面一行調用函數時會報錯
fun()
複製代碼
能夠看到在上面代碼中, 既有fun變量, 又有fun函數的代碼中, 後面提高的函數會覆蓋先前提高的變量, 因此最後fun指的是函數, 再給他賦值一個字符串, 就會報錯了.
在預解析過程當中,函數表達式進行的是變量聲明提高,而不是函數聲明提高。提高後變量內部存的是一個 undefined。在前面進行函數方法調用,數據類型會提示錯誤。
建議:定義函數時,最好使用 function 關鍵字定義方式,這樣函數聲明提高能夠永遠生效。
console.log(foo);
var foo = function(){
console.log(3)
}
console.log(foo);
foo();
複製代碼
在預解析以後,根據新的代碼順序,從上往下按照既定規律執行 js 代碼。