js關於靜態快照(snapshot)的問題
阿新 • • 發佈:2019-01-05
有這麼一個情景,JS程式碼 如下:
- var map = ['Mr' : 'Mr' , 'Ms' : 'Ms'];//可能有很多個
- var hello = [];
- function say(call , name){
- console.log(call + " : " + name );
- }
- //補全程式碼
- bababa~~~~
- //補全程式碼
- hello.Mr('JuMorZhu') // 控制檯輸出 Mr : JuMorZhu
- hello.Ms('Fan BingBing') // 控制檯 Ms : Fan BingBing
- 一開始我想到的是這樣:
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] )
}
你再試試,怎麼樣?感受到閉包的強大了吧~