標籤:
額……寫部落格什麼的好像很難的樣子……腦子一下子空了~~~
算了不矯情了,就當做捋一捋~~沒準寫著寫著就High了。
js範圍可以簡單理解兩句話。由上到下,由內到外
(一)預解析
我們來看一段代碼
alert(a);var a = 2;
運行結果是undefined。在使用var聲明變數但未對其加以初始化時,這個變數的值就是undefined。即a = undefined
function a() {console.log(1);}alert(a);
運行結果:
在預解析階段JS解析器會找關鍵字var,function,變數等。
這時存入的是一段代碼塊,即 a = function a() {
console.log(1);
}
在全域範圍中遵循一個簡單規則由上而下,在看一段代碼,猜一猜結果吧
alert(a);function a (){ alert(4); }var a = 1;alert(a);function a (){ alert(3); }alert(a);
結論:JS 的預解析遇到重名的只留一個, 變數和函數重名了,就只留下函數
(二)執行環境及範圍的概念
執行環境定義了變數或函數有權訪問的其他資料,決定了它們各自的行為。每個執行環境都有一個與之相關的變數對象。環境中定義的所有變數和函數都儲存在變數對象中。某個執行環境中的所有代碼執行完畢後,該環境被銷毀,儲存在其中的所有變數和函數定義也隨之銷毀。
每個函數都有自己的執行環境。
fn1執行完畢後函數的執行環境被銷毀,在函數內聲明的變數a也隨之銷毀。
原諒我一直停留在小學時期的畫圖水平吧~~
當試行流進入一個函數時,函數的環境就會被推入一個環境棧中。而在函數執行之後,棧將其環境彈出,把控制權返回給之前的執行環境。
到這裡插一句話,像我的例子裡這樣執行的函數都是同步滴~~同步任務在執行棧中~~推薦閱讀阮一峰大神的JavaScript 運行機制詳解:再談Event Loop
www.ruanyifeng.com/blog/2014/10/event-loop.html
(三)範圍鏈
當代碼在一個環境中執行時,會建立一個範圍鏈。範圍鏈可以保證對執行環境有權訪問的所有變數和函數的有序訪問。範圍的前端始終都是當前執行的代碼所在環境的變數對象。範圍鏈中的下一個變數對象來自包含(外部)環境。範圍鏈的最後一個對象始終是全域執行環境的變數對象。即範圍鏈遵循由內到外的簡單規則
現在把我那張小學生水平的圖稍作改動
fn1的範圍鏈,開始是fn1的變數對象,然後是來自包含環境的變數對象,在這裡是全域變數對象。
fn2執行時,執行a(),遇到arg1會順著範圍鏈尋找arg1,會先從函數a變數對象中尋找arg1,沒有就去範圍鏈上的下一個變數對象fn2的變數對象上尋找,沒有就繼續範圍鏈上下一個變數對象全域變數對象中尋找,這裡找到了arg1 = true.
總結一下,內部環境可以通過範圍鏈訪問所有外部環境,但外部環境不能訪問內部環境中的任何變數或函數。
(四)沒有塊級範圍
在JavaScript中沒有塊級範圍。
嘿嘿==,關於這個問題只要記住這句話就夠了~~額……當然不會就說這麼一句話,不來點乾貨我都不好意思==
在其他類c語言中,由花括弧{}封閉的代碼塊都有自己的範圍,但是js沒有塊級範圍!!!
如果存在塊級範圍應該報錯,因為a是一個局部變數,在全域是找不到a的。
但是運行結果a = 9,所以不存在塊級範圍。
(五)this
(六)call
JavaScript範圍學習筆記