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

作者: Kenqr (function(){})()   2016-11-25 15:40:24
抱歉,原本的寫法有錯。
函數被 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,對我們也沒有影響。
作者: iamshuichi (vincent)   2016-11-27 03:21:00
謝謝你,成功了,雖然原理還有點不太懂我再好好思考一下

Links booklink

Contact Us: admin [ a t ] ucptt.com