為了方便理解我們先看一段程式碼
a = 2;
var a;
console.log( a );
複製程式碼
得到的結果是什麼呢,undefined、ReferenceError異常、2還是其他呢 實際上這裡會輸出2,為什麼呢,我們再看
console.log( a );
var a = 2;
複製程式碼
結果又是什麼呢? 答案是undefined
要了解這些,我們就需要了解作用域是什麼了。
那麼作用域是什麼呢,簡單來說就是機器再執行某段程式碼時候的程式碼存在的環境。
var color = "blue";
function changeColor() {
var anotherColor = "red";
function swapColors() {
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
// 這裡可以訪問color、anotherColor和tempColor
}
// 這裡可以訪問color和anotherColor,不能訪問tempColor
swapColor()
}
// 這裡只能訪問到color
changeColor()
複製程式碼
這段程式碼涉及到三個執行環境:全域性環境、changeColor()的區域性環境和swapColor()的區域性環境。也就是作用域。
我們可以看出,每一個花括號形成了一個作用域,越內部的作用域可訪問到越多,這是因為JavaScript的程式碼執行時會向上訪問,如果當前作用域找不到要訪問的物件,對向上一級作用域查詢,最終查詢到全域性作用域,都查詢不到的話丟擲錯誤。
回到開頭的程式碼,在我們看來var a = 2
是一段程式碼,而JavaScript不這麼看,它看到的是
var a
和a =2
JavaScript會將申明移到作用域的頂端,所以第一段程式碼在console.log(a)的時候就訪問到了值,而第二段程式碼在console.log(a)的時候只做了var a
動作,a沒有實際的值,所以結果是undefined。
——ps:es6 出現了const和let兩種申明方式,這兩種申明不會進行提升
a = 2;
let a;
console.log( a ); // Uncaught ReferenceError: a is not defined
複製程式碼
參考資料: 《JavaScript高階程式設計》 《你不知道的JavaScript(上卷)》