用setTimeout来实现setInterval
先用setTimeout正确地实现一个setInterval:
/* 示范1 正确 */ function timeoutToInterval(func, time){ function inside(){ func(); setTimeout(inside, time); } setTimeout(inside, time); } timeoutToInterval(()=>{ console.log( '呀咩爹~' ); }, 1000)
将定时器放到需要执行任务的后面,这样就直接解决了上面的两个问题。
我们看一个不用inside包裹的实现方式:
/* 示范2 错误 */ function timeoutToInterval(func, time){ setTimeout(function () { func(); setTimeout(arguments.callee, time); }, time) } /* arguments.callee 等价于 function () { func(); setTimeout(argumrnts.callee, time); } */
看这种实现方式,用argument.callee来充当内层定时的回调函数,其值等于外层定时器的回调函数。
看起来好像也挺简便的,但是它会有兼容性问题,ES5的严格模式就严禁使用arguments.callee。
所以最好还是外层定时器的回调包在一个函数中,然后再由一个定时器去调用这个函数。
你可能还有一个问题,我把外层的回调包在一个函数中,那我在函数的定时器里面直接去调用的外层函数不就好了,形成一个递归,不是也能实现想要的效果?就像下面这样
/* 示范3 错误 */ function timeoutToInterval(func, time){ function inside(){ func(); setTimeout(inside, time); } inside(); }
答案很简单,因此两种实现方式在循环定时器刚启动时,效果是不一样的。示范3的方式,在循环定时器刚被调用时,回调函数会立即执行,而示范1则是在过了设定了间隔时间之后,才会执行第一次的回调任务。
【为什么要用setTimeout模拟setInterval ?_若水弹丸之地-CSDN博客】https://blog.csdn.net/b954960630/article/details/82286486