在開始之前,我們先來看一段代碼:
var name = 'window';
function display() {
alert(name);
var name = 'local';
alert(name);
}
display();
請不要去運行代碼,根據你掌握的js知識來給出你的答案,我相信會有很多童鞋會說這很簡單啊,不就是window和local嗎?!然而事實真的是這樣嗎?
作用域
要理解詞法作用域,首先要明白什麼是作用域。作用域是變量和函數的可訪問範圍,控制着變量和函數的可見性及什麼週期。一般來說js中的作用域可以分爲全局作用域和局部作用域(es6還有塊級作用域)。而JavaScript的詞法作用域採用的是靜態作用域
- 靜態作用域:指詞法作用域在詞法分析階段就已經確定了,不會改變,可以簡單理解爲取決於源代碼。
- 動態作用域:會根據程序的調用、執行而改變,取決於在什麼地方被調用。
詞法作用域
一個文檔流中的JavaScript代碼的執行順序大概分爲以下幾個步驟:
1、讀入第一個代碼片段(js引擎不是一行一行的分析代碼,而是一段一段的分析執行)。
2、進行詞法分析,檢查語法是否有錯誤(比如是否少了括號...),如果有錯誤則拋出錯誤。
3、對var定義的變量和function關鍵字定義的函數進行‘與解析’,也就是我們常說“變量提升”。
4、執行代碼段,如果發生錯誤,跑出錯誤異常。
5、如果還有下一段代碼,則繼續讀入下一段代碼,並且重複第2步。
6、結束。
附一張圖:
我們來分析開篇的代碼:
調用display函數的時候,讀入代碼片段,進入第二步進行詞法分析,未發現錯誤,然後進行第三部,進行與解析,即變量提示,將變量name提升到函數的第一行,此時只有var name,並未進行賦值,因此第一個alert的值是undefined;繼續執行nam = ‘local’;因此第二alert的值爲local。所以正確答案是undefined和local。