两个方法都是用于执行定时任务的函数,主要差异存在于执行次数和间隔的处理方式。
setTimeout
在一定延迟后执行一次指定的函数或代码块。执行完成后停止计时。
setInterval
每隔一定时间重复执行指定函数,会不断执行直到被取消或者页面销毁。
js 中 定时器不能准时执行 ,主要原因包括以下几点:
this
指向问题:如果回调函数是某个对象的方法, this
会指向全局,而不是对应的对象。
const name = "window";
const obj = {
name: "obj",
say: function () {
console.log(this.name);
},
};
setTimeout(obj.say, 10); // log: window;
可以通过 箭头函数 、 call/bind/apply 、 function 函数 解决 this
指向问题。
浏览器是通过消息队列去维护任务,要执行一段异步任务,需要先将任务添加到消息队列中。不过 通过定时器设置的回调函数比较特殊, 需要在指定的时间间隔被调用,而消息队列中的任务是按照顺序执行的,为了保证回调函数在指定的时间内执行,不能将定时器任务添加到消息队列。
对于时间精度要求高的动画效果来说, requestAnimationFrame 函数是一个好选择。
节流(Throttling)和防抖(Debouncing)是两种常见的性能优化技术,用于限制函数的执行频率。在 JavaScript 中一般通过定时器和闭包实现。
function throttle(func, delay) {
let lastExecTime = 0;
return function () {
const context = this;
const args = arguments;
const currentTime = new Date();
if (currentTime - lastExecTime > delay) {
func.apply(context, args);
lastExecTime = currentTime;
}
};
}
function debounce(func, delay) {
let timeout;
return function () {
const context = this;
const args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function () {
func.apply(context, args);
}, delay);
};
}