about 2 years ago

參考影片:JavaScript VM internals, EventLoop, Async and ScopeChains
影片主要介紹 JS VM如何解析JS Code並在執行管理記憶體,進而解釋了 value scope、closure的產生,圖片截自影片

  1. Compilation:JS和一般的Interpreting language不太一樣,如Shell script,他們最大特性是 當程式正在執行該行,他絕對不知道下一行內容是什麼;相反的,JS在執行之前會先掃過整個檔案,將合法的變數(用var宣告)和函式宣告放入Stack中,這也是Value Hoisting的原因 但此時還沒有賦值,而function則儲存pointer,指向一個BLOB,JS目前還沒掃過function內容
    2.Execution:當JS掃描完後,接著就是執行,此時才會把變數賦值,如果函式內呼叫了為存在變數,他會往parent的stack(or heap)中找,找不到就會噴Error,反之如果子母函式都宣告相同變數,則子函式會優先使用自己的(Value Shadowing) 。值得注意的是 如果JS執行到function時會動態產生heap,同時在跑Compilation和Execution,動作是一樣的

實驗一.

var a = 2
console.log(a,b) //2 undefined
var b = 5

實驗二.

var c = 2
console.log(c,d) // Error: d is not defined
d = 5

3.Garbage Collection:每個執行中的函式,除了有自己的heap外,還會保留一個指回母函式scope的pointer,可以用來取得母函式的變數


而GC回收機制就是當函式執行結束且沒有其他pointer指向他時,JS VM回收記憶體

而Closure存在的原因便是 某變數儲存了母函式回傳子函式的pointer,即使母函式執行結束,但是依然有變數儲存著pointer,所以造成記憶體無法回收!
參考MDN定義:Closures are functions that refer to independent (free) variables (variables that are used locally, but defined in an enclosing scope). In other words, these functions 'remember' the environment in which they were created.
而母函式中的變數即是environment

function add(a){
   var count = 0
   return function(){
      count+=a 
      return count
   }
}
add3 = add(3)
add3() //3
add3() //6

[補充]我後來又有找到其他資料,更詳盡的補充了Function的作用,詳細請看JS - 關於Object、Function的屬性、作用域與種種

← How Browser work - 瀏覽器運作原理 Angular2 - 自置DatePicker →
 
comments powered by Disqus