在JS中很重要的觀念就是hoisting,中文叫做「提升」。先來看看以下程式碼:
var a ='Hello World!'
function b(){
console.log('Called b!')
}
b();
console.log(a)
可想而知會印出:
//Called b!
//Hello World!
那如果將b()和console.log(a)放到程式碼前面呢?
b();
console.log(a)
var a ='Hello World!'
function b(){
console.log('Called b!')
}
JS都是逐行逐行執行的,照理來說函式b沒有被宣告就被執行,應該會報錯,但事實不然,b()跟console.log(a)都不會報錯,b()會執行程式,a則會報個undefined:
//Called b!
//undefined
這是因為hoisting。
網路解釋的hoisting
比較常看到的解釋是說hoisting會在執行時,把變數和函式提升到程式碼的頂部:
function b(){
console.log('Called b!')
}
var a;
b();
console.log(a)
var a ='Hello World!'
Anthony Alicea的hoisting
首先我們必須先明白,電腦並不是直接執行我們寫的JS code,而是透過一個轉譯器「syntax parser 語法解析器」來檢查我們寫的程式碼,並轉譯成電腦懂的語言讓電腦去執行。
轉譯給電腦後,JS會製造出一個execution context執行環境,被執行的程式碼會被包起來裝在執行環境中,而執行環境分為兩個階段:
- Creation Phase 創造階段
- Execution Phase 執行階段
在Creation Phase時,JS會自動幫變數和函式製造出記憶體空間,所以在執行前,JS已經知道有這個變數a還有函式b()。
但在執行前,JS只知道有這個變數a,還不知道a的值是多少,設值是執行後才會知道的,所以JS會給undefined這個預設值。
Creation Phase 創造階段
JS:哦哦我知道有a這個變數,也知道b這個函式!b要執行的是console.log(‘Called b!’),但我還不知道a會是多少,而a的預設值是undefined。
b();
console.log(a)
var a ='Hello World!'
function b(){
console.log('Called b!')
}
// Called b!
// undefined
Execution Phase 執行階段
JS:我知道a是多少了!!是Hello World!
b();
console.log(a)
var a ='Hello World!'
function b(){
console.log('Called b!')
}
console.log(a)
// Called b!
// undefined
// Hello World!
沒宣告就執行→還是會報錯
b();
console.log(a)
function b(){
console.log('Called b!')
}
//Called b!
//Uncaught ReferenceError: a is not defined
因為根本沒有宣告a,JS的記憶體中沒有a這個變數。
undefined跟ReferenceError: a is not defined 有何不同?
undefined:代表這個值還沒被設定,而undefined是JS中特殊的值(value)
var a;
console.log(a)
if(a === undefined){
console.log('a is undefined')
}else{
console.log('a is defined')
}
// undefined
// a is undefined
a === undefined
如果沒有var a;
console.log(a)
if(a === undefined){
console.log('a is undefined')
}else{
console.log('a is defined')
}
// Uncaught ReferenceError: a is not defined
因為JS在記憶體中找不到a,所以就會報錯。
undefined是JS中特殊的value。
老師建議沒事不要把執行放在宣告前,很容易搞錯,還是按照順序就好嚕;
var a ='Hello World!'
function b(){
console.log('Called b!')
}
console.log(a)
b()
// Hello World!
// Called b!
至於要用網路上廣泛的解釋方式還是老師的解釋,我是覺得沒差,反正知道結果就好了。