1. 程式人生 > >js關於靜態快照(snapshot)的問題

js關於靜態快照(snapshot)的問題

有這麼一個情景,JS程式碼 如下:

  1. var map = ['Mr' : 'Mr' , 'Ms' : 'Ms'];//可能有很多個
  2. var hello = [];
  3. function say(call , name){
  4.     console.log(call + " : " +  name );
  5. //補全程式碼
  6. bababa~~~~
  7. //補全程式碼
  8. hello.Mr('JuMorZhu') // 控制檯輸出 Mr : JuMorZhu
  9. hello.Ms('Fan BingBing') // 控制檯 Ms : Fan BingBing
  10. 一開始我想到的是這樣:

for( var x  in map){

  hello[x] = function(name){

               say(map[x],name)

   }

}

感覺挺簡單的,自己還在得意中的時候控制檯給我來了一波冷水。。。(+﹏+)~,輸出的都是Ms : Fan BingBing,我擦,你是有多喜歡范冰冰!!!

原因是這樣的,有沒有聽過這麼一個名詞: 靜態快照,是這樣的,當你在執行這段程式碼的時候,Js首先進入預編譯階段,因為你建立函式的時候沒有立即執行,所以JS在預編譯的時候就會引用這個變數而不是這個變數的值,當你的函式執行的時候才會去找這個變數,在它找這個變數的時候他找不到,就會返回上一層作用域去找這個變數,而這時這個變數是map[x],而x現在是map陣列的最後一個索引,也就是Ms,所以此時無論你hello中有多少個元素,都只有一種輸出結果,也就是在這種情況下建立的函式不支援靜態快照。

所以你需要換個思路了~

如果說函式執行的時候才去找變數,那麼我們問什麼不把它執行下呢,這時候我們用到了閉包。

再來看看用閉包寫的程式碼:

for(var x in map){

  hello[x] = (function( call ){

    say(call,name)

})( map[x] )

}

你再試試,怎麼樣?感受到閉包的強大了吧~