Re: [问题] setTimeout与循环的问题

楼主: iamshuichi (vincent)   2016-11-24 22:44:07
<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(){})()》之铭言:
: ※ 引述《shadowjohn (转角遇到爱)》之铭言:
: : for (var i=0; i<3; i++) {
: : setTimeout("audioPlay[i]", 500);
: : }
: : 上面这样写是不行的
: : 请改成下面这样
: : for (var i=0;i<3; i++) {
: : (function (index) { //加包的一层
: : setTimeout(function () {
: : audioPlay[index];
: : }, 500);
: : })(i); //带入循环的 i 值,会变成这个加包的function,变成 index 放入
: : }
: : 这样写就不用改太多了 :)
: 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,对我们也没有影响。
作者: eight0 (欸XD)   2016-11-24 23:41:00
这和this有关 把 audioX.play 改成 function(){audioX.play()}
作者: TETZ (你今天宅了吗?)   2016-11-25 00:38:00
应该是audioPlay[i]要变成audioPlay[i]()吧欸不对 原本那样应该ok不然就是用楼上的方法
作者: xdraculax (首席怪叔叔)   2016-11-25 07:01:00
加上 document.getElementById

Links booklink

Contact Us: admin [ a t ] ucptt.com