標籤:
範圍是javascript老生常談的問題,在面試題中也經常出現。此文記錄本人對js範圍的理解。從以下三個方面深入探討js範圍和js範圍鏈。
1、什麼是範圍?
2、什麼是範圍鏈?
3、常見面試題。
一、什麼是範圍?
熟悉編程的人都接觸過範圍,比如全域變數和局部變數之分。範圍是變數和函數可以訪問的範圍,即範圍控制著變數和函數的可見度和生命週期。
var name = "Aralic";function person () { //局部變數 var age = "22"; console.log(country) // "china" console.log(name); // ‘Aralic‘ console.log(age); // 22}person();
在這段代碼中,函數person就建立一個範圍,範圍裡面定義了一個變數age,在函數person外面是無法訪問這個變數的。但是在函數person內部是可以訪問到變數name,
因為name是函數person外面定義的,相對函數person是全域變數。
二、什麼是範圍鏈?
其實上面的例子已經出現了範圍鏈了。本來想畫圖解釋的,可惜畫圖功底實在太差了。還是上代碼吧。
var country = "china";function china () { var name = "Aralic"; function person () { //局部變數 var age = "22"; console.log(country) // "china" console.log(name); // ‘Aralic‘ console.log(age); // 22 } person(); }china ();
在函數person中,訪問country的過程:先從函數內部找,發現沒有country這個變數,那玩外層函數china找,結果還是沒有找到,那繼續往外找,結果找到了,不容易啊,嘿嘿,那這就是範圍鏈,一環扣一環,很厲害,有木有!
擴充:看到這裡,有小夥伴就要問了,假如在函數person裡面也定義一個變數country=“American”,那結果會是怎麼樣?會不會變數衝突?
大聲告訴你,不會衝突,結果就是直接列印出來American。不會向外層尋找了。這樣就形成了一條完整的範圍鏈,如果找到瀏覽器頂層window還沒有訪問到目標變數和函數,
那直接返回指令碼錯誤!
效能相關小技巧: 如果函數嵌套比較深,那麼我們在最裡面函數中用原生方法比如,document.getElementById(id); 那麼這個document我們是不是需要一層一層向外尋找,
那考慮到效能問題,我們是不是可以直接在函數裡面把document賦值給一個變數,那每次只要訪問這個變數就終止尋找了!
三、常見面試題:
我們已經學習了範圍和範圍鏈的知識,那麼下面來看幾個面試題。
第一題:
var name = "Aralic";function person () { console.log(name); var name = "Aralic";
}person();
博主第一次見到這個題目的時候,以為答案是Aralic,有沒有人和我想的一樣的?
在函數執行前,javascript存在先行編譯過程。
當調用函數person的時候會先先行編譯,把變數和函式宣告提升,轉成
function person () { var name; //不賦初始值 console.log(name);// 輸入undefined var name = "Aralic"; console.log(name) // 輸出Aralic} person ();
第二題:
var name = ‘Aralic‘; function person() { console.log(name); } function test() { var name = ‘tom‘; person(); } test();
這個題目看起來有點繞,先執行test函數,然後在test函數裡面調用person函數,執行person函數,列印name變數,那到底name變數是從test函數裡面找,還是直接存取最外面的name全域變數。這個題目和範圍鏈有關,說起來,person和test函數地位是相同的,所以是直接從最外面找name。
更多相關問題:請閱讀《單頁web應用》第二章節,講的比較詳細。
JavaScript範圍(鏈)學習筆記