少侠留步,看看下面的代码
const setTimeoutVal = setTimeout(() => { console.log('setTimeout'); }, 1000)
console.log('setTimeoutVal', setTimeoutVal);
clearTimeout(setTimeoutVal)
一.对于 setTimeout函数来说,
- 它是
JavaScript
中常见的一个API
。 - 它接收两个参数:一个是要执行的函数和一个延迟时间(以毫秒为单位)。
- 前面这个参数我们可以传匿名函数:
setTimeout(function() { console.log('setTimeout'); }, 1000)
- 或者 显式函数
setTimeout(function timeout() { console.log('setTimeout'); }, 1000)
-
或者 上面例子中的箭头函数
-
在上面这个例子来说意思就是在
1000ms
之后我们执行setTimeout
函数中的回调函数。 -
这里需要注意,
setTimeout
函数中的回调函数会在事件循环的下一个循环中执行。 -
也就是说,在
setTimeout
函数执行完毕之后,会先将回调函数放入事件循环的队列中,然后继续执行其他任务,直到事件循环的下一个循环中,才会执行回调函数。
setTimeout
在JavaScript
中属于宏任务
常见的宏任务包括:setTimeout
、setInterval
、requestAnimationFrame
等。
const setIntervalVal = setInterval(() => { console.log('setInterval'); }, 1000)
console.log('setIntervalVal', setIntervalVal);
clearInterval(setIntervalVal)
二.对于setInterval函数来说,
-
它和
setTimeout
函数类似,也是接收两个参数:一个是要执行的函数和一个延迟时间(以毫秒为单位)。 -
前面这个参数我们可以传入的函数也是跟
setTimeout
函数相同 -
在上面这个例子来说,意思是在
1000ms
之后我们执行setInterval
函数中的回调函数。 -
这里需要注意,
setInterval
函数中的回调函数会每隔指定的延迟时间执行一次。这个跟setTimeout
函数不同,setTimeout函数中的回调函数只会执行一次。 -
setTimeout
函数表示的是在指定的延迟时间之后执行一次回调函数,setInterval
函数表示的是每隔指定的延迟时间执行一次回调函数。 -
所以这就决定了它们适用的业务场景不同。
- 我们在需要反复刷新的业务逻辑中,一般会使用
setInterval
函数 - 而
setTimeout
函数则试用在延迟某些事务或者方法 setInterval
在JavaScript
中也属于宏任务
- 我们在需要反复刷新的业务逻辑中,一般会使用
三.我们调用这两个函数的时候,它们都是有返回值的。
- 这两个返回值都是数字类型的,表示的是一个
ID
,我们可以通过这个ID
来取消对应的定时器。 - 取消定时器的方式是通过
clearTimeout
和clearInterval
这两个函数。 - 这两个函数的参数就是前面提到的返回值。
四.在谈到它们的this指向时
需要注意,这两个函数的this
指向都是window
。
关于this的玩法,玩转this指向
五.我还想玩一下这两个函数如果后面的参数赋值为0或者负数是什么情况呢?
-
我发现我把
timeout
这个参数赋值为负数的话,还是可以打印,并没有报错。 -
后面我发现其实负数或者赋值为0的话,其实是一样的,
-
因为
setTimeout
函数的第二个参数是一个延迟时间,如果这个延迟时间小于0的话,其实它还是会被认为是0。 -
在它为0时表示希望立即执行,但是它还是会在
事件循环
的下一个循环
中执行。 -
后面思考了一下其实这么做也有道理的,如果我们如果让它一直调用的话,
其实它就会一直占用着事件循环的资源,这样就会导致其他任务无法执行。
所以为了避免这种情况的发生,让它在事件循环的下一个循环中执行,这样就不会一直占用资源了。
-
查阅了资料后,发现一般规定定时器最小的时间间隔为4ms。
但是我发现如果setInterval
第二个参数设置为0或负数的时候,它就会一直执行下去,
直到我们手动取消它。
setTimeout(() => { console.log('setTimeout'); }, -1)
setInterval(() => { console.log('setInterval'); }, 0)
- 负数我们玩过了,我们来试一下嵌套呢?
setInterval
的嵌套,在开发过程中暂时没遇到
不过我们来玩一下setTimeout
的嵌套,
setTimeout(() => {
console.log('(3层)第一层setTimeout');
setTimeout(() => {
console.log('(3层)第二层setTimeout');
setTimeout(() => {
console.log('(3层)第三层setTimeout');
}, 1000);
}, 1000);
}, 1000);
setTimeout(() => {
console.log('(2层)第一层setTimeout');
setTimeout(() => {
console.log('(2层)第二层setTimeout');
}, 1000);
}, 1000);
最后这个打印结果就让大家自己去玩。