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] )

}

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

 

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