2015年10月22日 星期四

[JavaScript] 在 for loop 中,使用 var 宣告 object 並在 async function 呼叫該物件時的 scope 問題

之前在寫 javascript 有碰到在 for loop 中,使用 var 宣告 object 並在 async function (例如 event)呼叫該物件時的 scope 問題。最近有空把它整理出來。

以下面這個範例為例,正常預期是依據按鈕是 hello 1、hello 2....點支下去 alert 的分別是 hello 1、hello 2....等,跟按鈕顯二的文字一樣。

在下面的例子中,在 onclick event 中, alert 的都是 hello 5
但在 for loop 中時,console.log(say.hello()); 是符合預期的。
這應該 var scope 範圍,和 var say 物件和 var i 因為 call by reference 的關係,reference 到最後一個實體
(因使用 alert 的關係,要點擊右上角 edit in JSFiddle 才能正確執行)



最簡單的解法是使用 let 來宣告,如下例 (只有 chrome 和 edge 可以用)
只改 var say => let say 來說明

但這個方法最主要問題是目前還有許多瀏覽器未支援,並不適合用在客戶端的產品上
Ref: http://caniuse.com/#search=let



另一個想到解法是使用 array 的 forEach 讓其產生獨立的 scope 空間
沒 forEach 之類的怎麼辦!?只好硬幹建一個 array 塞進入 XD
如下



那還有沒有其他解法?

JavaScript.tw FB社群:施文祥、Yuren Ju 
提供的 babel,compiler 出來的方法
把 loop 內改成 function ,在 loop 中呼叫 function



JavaScript.tw FB社群:Ly Cheng 
提供使用匿名函數 + bind 方式來解



同理可證
直接整個用匿名函數也能解,但效能可能就不怎麼樣

1 則留言:

  1. Firefox 預設是跑 JavaScript 1.6, 遇到 JavaScript 1.7 才有的 let, Firefox 就不行了. 但是只要宣告使用版本 type="application/javascript;version=1.7" , Firefox 就可以用 let 了.

    回覆刪除