setInterval与 setTimeout详解
setTimeout
和
setInterval
都是 JavaScript 中用于设置定时器的函数。
setTimeout()
语法
setTimeout(fn, delay, param1, param2, /* … ,*/ paramN)
-
fn: 定时器到期后,将要执行的函数。
-
delay(可选): 定时器在执行指定的函数或代码之前应该等待的时间,单位是毫秒,省略后默认是0。非数字的延迟值将被静默强制转化为数字,但这个转化未发生意外,例如:
"1秒"
最终被强制转换为数字0
,因此,不要使用字符串来表示 delay值,而要始终使用数字。 -
param1
, …,paramN
:fn
的附加参数,定时器到期,作为参数传递给fn
指定的函数。
清除定时器clearTimeout()
消除定时器。
let a = setTimeout(fn, 1000) // setTimeout会返回一个timeoutID(一个正数),表示定时器的编号
clearTimeout(a) // 消除定时器
setTimeout()
是异步函数,意味着计时器函数将不会暂停函数栈中其他函数的执行。
this问题
this 指向问题的原因
setTimeout()
函数会在指定的时间间隔之后执行指定的代码。这个代码块是在一个独立的执行环境中执行的,而不是在调用 setTimeout()
的函数的执行环境中执行的。
意味着,在 setTimeout()
中执行的代码块中,this
关键字的值可能与调用 setTimeout()
的函数中的 this
值不同。默认情况下,this
将引用全局对象 window
(在浏览器环境中)或 global
对象(在 Node.js
等环境中)
const myArray = ["zero", "one", "two"];
myArray.myMethod = function (sProperty) {
console.log(arguments.length > 0 ? this[sProperty] : this);
};
myArray.myMethod(); // 输出 "zero,one,two"
setTimeout(myArray.myMethod, 1.0 * 1000); // 在 1 秒后输出 "[object Window]"
解决办法
使用包装函数
一、使用Obj对象
// 假设有一个对象 obj,它有一个方法 showMessage
const myArray = {
arry: ["zero", "one", "two"],
myMethod: function (sProperty) {
console.log(arguments.length > 0 ? this.arry[sProperty] : this.arry);
};
};
// 使用包装函数确保在 setTimeout 中的上下文是 obj
function wrapper() {
myArray.myMethod();
}
// 调用 setTimeout 并传递包装函数
setTimeout(wrapper, 1000); // 输出: "zero,one,two"
二、匿名函数
setTimeout(function () {
myArray.myMethod();
}, 2.0 * 1000); // 在 2 秒后输出 "zero,one,two"
匿名函数和Obj对象充当了包装函数的角色,myArray.myMethod()
将作为普通的函数调用,而不是作为对象方法。这样,即使在 setTimeout()
执行时,执行环境发生了变化,myArray.myMethod()
仍然能够正确地在 myArray
上下文中执行。
三、箭头函数
setTimeout(() => {
myArray.myMethod();
}, 2.0 * 1000); // 在 2 秒后输出 "zero,one,two"
箭头函数会捕获其父作用域的 this
值。这样可以确保在 setTimeout()
中执行的代码中,this
的值与调用 setTimeout()
的函数中的 this
值一致。
使用Bind()
const myArray = ["zero", "one", "two"];
const myBoundMethod = function (sProperty) {
console.log(arguments.length > 0 ? this[sProperty] : this);
}.bind(myArray);
setTimeout(myBoundMethod, 1.0 * 1000); // 由于绑定问题,还是在 1 秒后输出 "zero,one,two"
setInterval()
语法
var intervalID = setInterval(fn, delay, arg1, arg2, ...);
-
fn: 定时器到期后,将要执行的函数。
-
delay(可选): 定时器在执行指定的函数或代码之前应该等待的时间,单位是毫秒省略后默认是0。非数字的延迟值将被静默强制转化为数字,但这个转化未发生意外,例如:
"1秒"
最终被强制转换为数字0
,因此,不要使用字符串来表示 delay值,而要始终使用数字。 -
arg1
, …,argN
:fn
的附加参数,定时器到期,作为参数传递给fn
指定的函数。
清除定时器clearInterval()
消除定时器,用法与clearTimeout()
一致。
同样setInterval()
也存在与setTimeout
一致的this
问题。
setInterval() 与 setTimeout() 的区别
触发方式:
setTimeout
:用于在指定的时间间隔后执行一次指定的代码。setInterval
:用于每隔指定的时间间隔重复执行指定的代码。
执行次数:
setTimeout
只会执行一次指定的代码,然后就会停止。setInterval
会重复执行指定的代码,直到被取消(通过clearInterval
函数)或者页面被关闭。
利用setTimeout 实现 setlnterval
function customSetInterval(callback, interval) {
function loop() {
callback();
setTimeout(loop, interval); // 在回调函数执行完后再次设置定时器
}
loop(); // 第一次调用
}
customSetInterval(function() {
console.log('Hello, World!');
}, 1000); // 每隔一秒输出一次 "Hello, World!"
setInterval
和 setTimeout
更多用法:
setInterval:
https://developer.mozilla.org/zh-CN/docs/Web/API/setInterval
setTimeout:
https://developer.mozilla.org/zh-CN/docs/Web/API/setTimeout