我知道的setTimeout
什么是setTimeout
简单来说它是一个定时器,是浏览器提供的一个api,用于延迟执行代码
它的语法是这样的:
var timer=setTimeout(function[,delay,args1,agrs2,...])
var timer=setTimeout(code[,delay])
setTimeout的第一个参数可以是function,也可以是一个字符串类型的代码片段(类似于eval那样的)
参数
| 参数 | 是否可选 | 描述 |
|---|---|---|
| function/code | 是 | 定时器要执行的函数主体,可以是函数,也可以是代码片段.(注意:不建议使用代码片段,因为跟eval一样不安全) |
| delay | 否 | 定时器需要延迟的时间毫秒数,如果没有设置默认为0 |
| ...args | 否 | 当定时器的第一个参数是函数时,将作为函数的参数传入 |
返回值
setTimeout返回一个int型的定时器id,用于后续的取消操作(clearTimeout)
function say(){
console.log('你好')
}
let timerId=setTimeout(say,10*1000);
clearTimeout(timerId) //定时器被取消、不在执行
注意:clearInterval,clearTimeout都可以用于取消定时器无论定时器id来源setInterval,setTimeout
如:
var time1=setTimeout(fn,1000);
clearInterval(time1)//这是可以取消定时器的
var time1=setInterval(fn,1000);
clearTimeout(time1)//这也是可以的
带参数的setTimeout
function say(name,week){
console.log(`你好,${name},今天是${week}`)
}
setTimeout(say,1000,'jojo','周五') //打印:你好,jojo,今天是周五
setTimeout中的this问题
其实这个问题比较简单、我们都知道正常情况下js中this指是的代码执行上下文的一个变量,有三种类型:
- 全局上下文(全局作用域)
- 无论是否在严格模式下,在全局执行环境中(在任何函数体外部)
this都指向全局对象。
- 无论是否在严格模式下,在全局执行环境中(在任何函数体外部)
- 函数上下文(函数作用域)
- 在函数内部,
this的值取决于函数被调用的方式。也就是谁调用、就指向谁,函数中的this是动态分配,执行的时候才确定
- 在函数内部,
- eval
如:
function say(){
console.log(this.name)
}
say();
//这里函数是直接执行的、没有直接调用者,所以this指向了window
var person={
name:'123',
say:say
}
person.say();
//这里执行say的主体是person,所以this指向person对象
再来看看setTimeout执行
var person={
name:'123',
say:function(){
console.log(this.name)
}
}
setTimeout(person.say,1000) //打印undefined
上面这段代码、看上去是person执行say方法
其实应该是这样的:
function setTimeout(){
var fn=arguments[0];
var args=[].slice.call(arguments,2);
if(typeof fn === 'function'){
fn.apply(globalThis,args)
}
...
}
setTimeout(person.say,1000)
//所以setTimeout中的的this指向globalThis
以下方法可以绑定this
//包装函数
setTimeout(function(){
person.say();
},1000)
//绑定this
var fn=person.say.bind(person);
setTimeout(fn,1000)
MDN提供了封装的函数
// Enable the passage of the 'this' object through the JavaScript timers
var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval;
window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2);
return __nativeST__(vCallback instanceof Function ? function () {
vCallback.apply(oThis, aArgs);
} : vCallback, nDelay);
};
window.setInterval = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2);
return __nativeSI__(vCallback instanceof Function ? function () {
vCallback.apply(oThis, aArgs);
} : vCallback, nDelay);
};
setTimeout执行时间
- 最小延迟时间: >=4ms
- 在浏览器中,
setTimeout()/setInterval()的每调用一次定时器的最小间隔是4ms,
- 在浏览器中,
- 最大延迟时间: 2147483647 ms (大约24.8 天)
- 由于浏览器数据存储机制导致(32位带符号整数存储)
- 定时器延迟执行的时间会大于给定的时间(setTimeout中的
delay参数)- JS
事件循环机制导致定时器会在主任务执行完后才开始
- JS