js一個關於作用域和執行環境的例子

在網上無意中看到一個關於js的作用域和執行環境的面試題,以前我也沒怎麼總是這些東西,經過一小段時間的研究,我慢慢開始明白其中的奧妙,這對以後寫程序還是大有幫助的。日誌代碼如下:

f = function() {return true;}; 
g = function() {return false;}; 
(function() { 
   if (g() && [] == ![]) { 
      f = function f() {return false;}; 
      function g() {return true;} 
   } 
})(); 
alert(f()); // true or false ?

可能大家一開始看到這個題目肯定都和我一樣猜到了,最後輸出的是false。那分析一下怎麼得出結論的吧。


首先給大家腦補一下([] == ![])得到的應該是true。其中的緣由的家慢慢去領會吧。然後用這個例子給大家普及一點作用域鏈的知識。

在這段js代碼執行下來的時候,會形成一條作用域鏈(我習慣把作用域鏈分層,可能這樣不科學,但是有助於我們理解),在作用域鏈(第一層作用域鏈)的外層就是第1,2,9,還有整個3-8行的代碼,在3-8行的代碼內部又衍生出一條新的作用域鏈(第二層作用域鏈),在3-8行的內部,匿名函數function和它內部就是第二層作用域鏈。每一層都會有個執行環境,在下一層的執行環境裏邊可以訪問上一層(或者更外層)執行環境中的變量,但是在上層執行環境中不能訪問下一層執行環境中的私有變量(解決這個問題就要用閉包的思想)。


執行的第一階段:在這個例子中的4行的if判斷中執行的g()函數其實首先會在if所在當前層找有沒有這個函數,如果沒有,然後再順着作用域鏈向上層尋找,因此首先會執行第6行的g()函數,返回true,因此,第一階段的if判斷爲什麼會返回true的疑惑就解決了。

執行的第二階段:接下來就要執行if判斷內部的代碼了,在代碼的第5行對前邊的f()函數進行了重寫(在f前邊沒有加var,因此就是覆蓋全局的f變量),因此在內存中原本保存的f()函數就變了,應該返回false了,因此,內存中的f()改變,最後在第一層作用域中alert(f())就返回false。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章