作用域
作用域,可簡單理解爲變量起作用的區域,如下圖所示:
此圖出自《你不知道的JavaScript 上篇》的詞法作用域一節,本例中有三個作用域完全嵌套而成:
- foo 所在的全局作用域
- a, b, bar所在的foo函數作用域
- c 所在的bar函數作用域
顯而易見,在函數作用域的嵌套中,內函數可以訪問到外函數的變量,而反過來,是不可以的
提升
爲什麼要先解釋作用域呢,因爲在每個作用域中,都存在自己的提升,接下來進入正題,什麼,是提升?
思考以下代碼的輸出:
var a = 2
console.log(a)
脫口而出:2啊
那麼這個呢:
a = 2
var a
console.log(a)
可能很多人會認爲,輸出undefined
,因爲看上去a在輸出的時候只是被聲明瞭而爲被賦值,但當你實際運行這段代碼,會發現,輸出是2。
原因就是代碼執行前,每個作用域內都有一個被稱爲提升的過程,所有變量的聲明會被提升到作用域頂端。
所以上述代碼實際上在運行時順序是這樣的:
var a
a = 2
console.log(a)
理解了提升,我們再來看以下代碼:
console.log(a)
var a = 2
會輸出什麼呢?答案是undefined
,請務必注意,提升只會把變量的聲明提升,變量的實際操作還是在執行時發生。所以上面的代碼實際上執行順序是這樣的:
var a
console.log(a)//undifined
a = 2
最後需要注意的點還有,函數聲明會被提升,而函數表達式不會。看他們的語法,聰明的你應該知道是爲什麼了吧
函數聲明,形如:function foo() {}
函數表達式,形如:var foo = function(){}