setTimeout
this 问题
- setTimeout 的第一个参数是回调函数,无论传入的是什么样的函数,在调用它的时候都是没有 this 指向的,所以默认都指向 window 对象(无论是否是严格模式);
- setTimeout 也不能直接使用 call 等方法;
setTimeout.call(myArray, myArray.myMethod, 2.0 * 1000); // 出错
要解决这个问题可以使用:
设置包装函数
包装函数可以是具名函数,也可以是箭头函数,它们唯一的区别就是在严格模式下函数中的 this 指向问题,具名函数中的 this 是 window,而箭头函数是 undefined。
setTimeout(function () {
console.log(this);
myArray.myMethod();
}, 1.0 * 1000);
使用 bind
setTimeout(myArray.myMethod.bind(myArray), 1.0 * 1000);
延时比指定值更长
- 嵌套延时:HTML 标准中规定,一旦 setTimeout 嵌套了 5 次,浏览器将强制执行 4ms 的最小超时;
- 非活动标签延时:为了优化后台标签的加载损耗(以及降低耗电量),浏览器会在非活动标签中强制执行一个最小的超时延迟;
- 超时延迟:浏览器(页面,操作系统)忙于其他任务,导致时间执行比预期晚;
毕竟 setTimeout 是一个异步的宏任务,是要加入任务队列里的,哪怕设置延时为 0 也是要比同步任务晚执行的。
- 加载页面时延时:当前标签页正在加载时,Firefox 将推迟触发 setTimeout() 计时器。直到主线程被认为是空闲的(类似于
window.requestIdleCallback()),或者直到加载事件触发完毕,才开始触发。 - webExtension:在浏览器扩展中 setTimeout 不会可靠的工作;
- 最大延时:浏览器内部以 32 位带符号整数存储延时,如果设置的时延超出了大约 24.8 天时就会溢出,导致定时器会被立刻执行;
requestIdleCallback
插入一个函数,这个函数将在浏览器空闲时期被调用。