JavaScript中setInterval()和setTimeout()的用法及区别
作者:乌 秋
一、setInterval()
1、setInterval() 是JavaScript的一个定时器函数,用于设置周期性的定时任务。它的语法如下:
setInterval(function, delay, param1, param2, …);
其中,function参数表示要执行的函数,delay参数表示定时器的时间间隔(以毫秒为单位),param1, param2, …表示传递给函数的参数(可选)。
setInterval()会不断地重复执行指定的函数,直到被取消或页面被卸载。每个时间间隔结束时,function函数都会被调用一次。例如,下面的代码会每隔1秒钟输出一次当前时间:
setInterval(function() { const now = new Date(); console.log(now.toLocaleTimeString()); }, 1000);
二、setTimeout()
1、setTimeout也是一个定时器函数,它允许我们在指定的时间后执行一次函数。
setTimeout(function, delay, arg1, arg2, …)
- 其中,function 是我们要执行的函数,delay 是延迟的时间(以毫秒为单位),arg1、arg2 等是传递给函数的参数(可选)。
- setTimeout 返回一个唯一的标识符,我们可以使用 clearTimeout 函数来取消这个定时器。代码如下:
// 延迟 1 秒后输出 "Hello, world!" const timerId = setTimeout(() => { console.log("Hello, world!"); }, 1000); // 取消定时器 clearTimeout(timerId);
这段代码定义了一个 setTimeout 定时器,它会在 1 秒后执行一个函数,输出字符串 “Hello,world!”。同时,它会将返回的计时器 ID 存储在变量 timerId 中。 接下来的一行代码调用了 clearTimeout 函数,并传timerId。这个函数会取消之前设置的定时器,从而避免了执行函数的操作。因此,这段代码最终不会输出任何内容。
三、setInterval()和setTimeout()的区别
setInterval() 和 setTimeout() 都是 JavaScript 中的定时器函数,但它们有以下几个区别:
1. setInterval() 在延迟指定时间后重复执行指定任务,直到被取消或页面关闭。而 setTimeout() 在延迟指定时间后执行指定任务,只执行一次;
2. setInterval() 的执行间隔时间是固定的,而 setTimeout() 可以动态调整延迟时间;
3. setInterval() 可能会存在累积性误差,因为它的执行时间是相对于上一次任务结束的时间计算的,如果执行的任务耗时超过了指定的时间间隔,就会出现累积性误差。而 setTimeout() 每次执行都是相对于上一次任务开始的时间计算的,不存在累积性误差;
4. setInterval() 可能会对性能产生影响,因为它会不断地重复执行指定任务,占用 CPU 资源。而 setTimeout() 只会在指定时间后执行一次任务,对性能影响较小。
因此,一般情况下,如果我们需要周期性地执行指定任务,就可以使用 setInterval();如果我们只需要在指定时间后执行一次任务,就可以使用 setTimeout()。
四、注意事项
使用setInterval()时要注意以下几点:
- delay参数的最小值是4毫秒,如果设置的值小于4毫秒,则会被强制转换为4毫秒。
- setInterval()返回一个定时器ID,可以使用clearInterval()函数来取消定时器。
- 由于JavaScript是单线程的,因此如果function函数执行的时间过长,可能会影响页面的响应性能。因此,建议在编写function函数时要尽量减少执行时间。
补充:常见的面试题
1、分析输出
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(new Date, i); }, 1000); } console.log(new Date, i);
输出:
5->5,5,5,5,5(->代表1s)
2018-08-14T08:20:05.694Z 5
2018-08-14T08:20:06.696Z 5
2018-08-14T08:20:06.697Z 5
2018-08-14T08:20:06.697Z 5
2018-08-14T08:20:06.698Z 5
2018-08-14T08:20:06.698Z 5
2、追问 1:闭包期望代码的输出变成:5 -> 0,1,2,3,4,该怎么改造代码?
方式一:
for (var i = 0; i < 5; i++) { (function(j) { // j = i setTimeout(function() { console.log(new Date, j); }, 1000); })(i); } console.log(new Date, i);
方式二:
for (var i = 0; i < 5; i++) { setTimeout( (function (j) { // j = i return function () { console.log(new Date, j); } })(i), 1000); } console.log(new Date, i);
存在错误的方式三
for (let i = 0; i < 5; i++) { setTimeout(function() { console.log(new Date, i); }, 1000); } console.log(new Date, i);//let,for循环外部访问不到i
追问 2:ES6
如果期望代码的输出变成 0 -> 1 -> 2 -> 3 -> 4 -> 5,并且要求原有的代码块中的循环和两处 console.log 不变,该怎么改造代码?
方式一:
for (var i = 0; i < 5; i++) { (function(j) { setTimeout(function() { console.log(new Date, j); }, 1000 * j); // 这里修改 0~4 的定时器时间 })(i); } setTimeout(function() { // 这里增加定时器,超时设置为 5 秒 console.log(new Date, i); }, 1000 * i);
方式二:promise
var p= Promise.resolve() for (var i = 0; i < 5; i++) { (function(j){ p=p.then(setTimeout(function() {//p=p.then()相当于实现链式操作 console.log(new Date, j); }, 1000*j )); // 这里修改 0~4 的定时器时间 })(i) } setTimeout(function(){ p.then(console.log(new Date, i)) }, 1000*i) ;
方式二:promise.all
const tasks = []; for (var i = 0; i < 5; i++) { // 这里 i 的声明不能改成 let,如果要改该怎么做? ((j) => { tasks.push(new Promise((resolve) => { setTimeout(() => { console.log(new Date, j); resolve(); // 这里一定要 resolve,否则代码不会按预期 work }, 1000 * j); // 定时器的超时时间逐步增加 })); })(i); } Promise.all(tasks).then(() => { setTimeout(() => { console.log(new Date, i); }, 1000); // 注意这里只需要把超时设置为 1 秒 });
总结
到此这篇关于JavaScript中setInterval()和setTimeout()用法及区别的文章就介绍到这了,更多相关setInterval()和setTimeout()用法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!