setTimeout&setInterval&任
setTimeout
几秒后执行一次代码。
当我们运行setTimeout或者setInterval的时候会立刻拿到一个数值,这个数值就是它们本身的一个返回值,你可以认为是它们的id或者是编号。
我们可以通过它们每次的返回值编号来清除它们

setInterval
每隔几秒后执行一次代码
任务队列
js是单线程,也就是说同一个时间只能做一件事,这也就意味着所有任务需要排队,前一个任务结束,才会执行后一个任务
(1)所有同步任务都在主线程里的执行栈(stack)里排队执行
(2)主线程之外,还存在一个"任务队列"。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复。
"任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,"任务队列"上第一位的事件就自动进入主线程。但是,由于存在"定时器",主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。

上图中,主线程运行的时候,产生堆(heap)和栈(stack),栈中的代码调用各种外部API,它们在"任务队列"中加入各种事件(click,load,done)。只要栈中的代码执行完毕,主线程就会去读取"任务队列",依次执行那些事件所对应的回调函数。
例题1:
var isOk = true
setTimeout(function(){
isOk = false
})
while(isOk){
}
console.log(3)
上面的代码什么也不会输出
原因是,因为一开始代码运行先把同步任务按顺序放到stack中执行,也就是会先执行var isOk = true和while(isOk){}因为只有stack里的同步代码执行完了,才会去任务队列里处理异步,而isOk一直是true,一直没结束所以不会继续往下执行也不会去执行setTimeout里面的代码
例题2:
for(var i = 0;i<10;i++){
setTimeout(function(){
console.log(i)
},1000)
}
//10个10
上面的代码最后会打印出10个10
例题解析:for循环是同步代码,会先放入stack里执行,每次循环都会创建一个定时器,for循环结束后i是10,开始执行异步setTimeout里的代码,因为有10个所以会打印出10个10
函数节流(使用方法要在监听事件里使用,比如input就是input事件里使用)
如果某一个函数在一定时间内连续执行了很多次,把前面的都忽略掉,我们以最后一次为准,也就是当你停下来的时候在一段时间后才会去执行,当你连续操作的时候就去不断的清除原来的计时器,新建新的计时器,然后去重新计时到指定时间才执行
var time
function fn(){
if(time){
clearTimeout(time)
}
time = setTimeout(()=>console.log('aaa'),3000)
}
fn()
fn()
fn()
改造
function throttle(fn, delay){
var timer = null
return function(){
clearTimeout(timer)
timer = setTimeout(function(){
fn()
},delay)
}
}
function fn(){
console.log('hell0')
}
var fn2 = throttle(fn, 1000)
fn2()
fn2()
``