Re: [問題] setTimeout與迴圈的問題

看板Ajax作者 (function(){})()時間7年前 (2016/11/25 15:40), 編輯推噓1(101)
留言2則, 1人參與, 最新討論串5/5 (看更多)
抱歉,原本的寫法有錯。 函數被 setTimeout 呼叫的時候,this 會被設定成 window, 所以呼叫有用到 this 的函數就會出問題。 這裡比較常見的作法是使用 closure 處理: var audios = [audio1, audio2, audio3]; var time = [0, 500, 1000]; for(var i=0; i<3; i++) { (function(index){ setTimeout(function(){ audios[index].play(); }, time[i]); })(i); } 這裡直接用 audios[i].play() 的話會有錯, 因為離開迴圈後 i 的值固定是 3, setTimeout 的時間到時就會變成執行audios[3].play()。 用 closure 包起來後, 外面的 function 每次執行會產生一個新的環境,一共 3 個。 每個環境有自己的 index,即使 i 改變了,index也不會受到影響。 另外也可以用 bind: var audios = [audio1, audio2, audio3]; var time = [0, 500, 1000]; for(var i=0; i<3; i++) { setTimeout(audios[i].play.bind(audios[i]), time[i]); } 因為懶了所以就不解釋了XD ※ 引述《iamshuichi (vincent)》之銘言: : <html> : <audio id="audio1" src="1.wav"></audio> : <audio id="audio2" src="2.wav"></audio> : <audio id="audio3" src="3.wav"></audio> : <button onclick="play()">Start</button> : <script> : var play = function() { : var audioPlay=[audio1.play, audio2.play, audio3.play]; : var time=[0, 500, 1000]; : for (var i=0; i<3; i++) { : setTimeout(audioPlay[i], time[i]); : } : } : </script> : </html> : 您的範例我看到了,是可以正常執行的 : 但是我套用上去就不行了 : 到底是發生了什麼事??? : >_< : ※ 引述《Kenqr (function(){})()》之銘言: : : var audioPlay = [audio1.play, audio2.play, audio3.play]; : : var time = [0, 500, 1000]; : : for(var i=0; i<3; i++) { : : setTimeout(audioPlay[i], time[i]); : : } : : 實際可執行的範例: : : https://jsfiddle.net/hzrw429z/1/ : : 第一行的 audio1.play() 拿掉括號改成 audio1.play, : : 因為這個陣列裡要放的是函數而不是函數的執行結果。 : : 寫成 audio1.play() 會在執行到宣告陣列這行時就播放了,函數也沒存進陣列裡。 : : setTimeout 這行,"audioPlay[i]" 拿掉雙引號改成 audioPlay[i]。 : : 因為 setTimeout 傳入字串時,是把字串內容當成函數內容執行。 : : 原本的寫法會在時間到時取出 audioPlay 陣列第 i 項的值, : : 取出後沒有做任何動作,所以什麼事都沒發生。 : : 修正的寫法會在呼叫 setTimeout 函數前先取得 audioPlay 的第 i 項, : : 取得的東西是一個函數,當成參數傳給 setTimeout。 : : 所以 3 次呼叫 setTimeout 相當於: : : setTimeout(audio1.play, 0); : : setTimeout(audio2.play, 500); : : setTimeout(audio3.play, 1000); : : 時間到時可以正確的分別執行 3 個函數。 : : 這個情況不需要使用 IIFE, : : 因為 audioPlay[i] 是在呼叫 setTimeout 之前就已經取值了。 : : setTimeout 在時間到時,呼叫第一個參數的函數時已經不會用到 i, : : 所以即使離開迴圈後 i 的值固定是 3,對我們也沒有影響。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.193.160.70 ※ 文章網址: https://www.ptt.cc/bbs/Ajax/M.1480059627.A.71E.html

11/27 03:21, , 1F
謝謝你,成功了,雖然原理還有點不太懂
11/27 03:21, 1F

11/27 03:21, , 2F
我再好好思考一下
11/27 03:21, 2F
文章代碼(AID): #1OD-hhSU (Ajax)
討論串 (同標題文章)
文章代碼(AID): #1OD-hhSU (Ajax)