js相关知识点总结+面试题

1、js执行顺序:同步任务 > 异步任务

所有同步任务都在主线程上执行,形成一个执行栈,异步任务放在任务队列中,一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

异步任务包含两部分:微任务和宏任务

宏任务中的方法:1. script (可以理解为外层同步代码,作为入口 )
2. setTimeout/setInterval
微任务中的方法:1.Promise 2. nextTick
总结:同步任务 > 微任务 > 宏任务
事件循环:宏任务 ==> 微任务 ==> 渲染 ==> 宏任务 ==> 微任务 ==> 渲染 ==> 宏任务
两个微任务,从上至下依次执行,两个定时器,如setTimeout,时间短的先放上面执行,一样就从上至下依次执行。
参考原文(推荐去看):
https://blog.csdn.net/u010227042/article/details/125284966

2、为什么输出的是5个5,而不是0,1,2,3,4

for(var i=0;i<5;i++){
   console.log('aaaaa')
  setTimeout(function(){
    console.log(i)
  },100)
}
for(let i=0;i<5;i++){
  console.log('bbbbb')
  setTimeout(()=>{
    console.log(i)
  },10)
}
// 输出:
aaaaa,aaaaa,aaaaa,aaaaa,aaaaa
bbbbb,bbbbb,bbbbb,bbbbb,bbbbb
0,1,2,3,4
5,5,5,5,5

因为:首先js是单线程,代码是从上到下一次执行,两个for循环是两个同步任务,在执行栈中先执行,setTimeout是异步任务,for循环在执行的时候,异步任务放在任务队列中排队等候,所以先输出了aaaaa和bbbbb,至于为什么输出了5次,是因为for循环先执行,且循环了5次,等执行栈中的for循环执行完,再执行任务队列中的setTimeout,setTimeout是异步任务中的宏任务,两个setTimeout根据等待时间的长短决定先执行谁,所以先执行下面的setTimeout。为什么输出的是0,1,2,3,4,而不是5,5,5,5,5是因为for循环的计数器变量i是用let声明的,let声明的变量只在let命令所在的代码块内有效,for循环体每次执行都是一个全新的独立的块作用域,且计数器变量i是在循环开始之前初始化,每次循环的i,只在当前块作用域有效,且互不影响,使用let声明的变量作为迭代器变量传入到 for循环体的作用域后,不会发生改变,不受外界的影响。如果把let i放在for循环外,那么跟var i效果一样了,这里要注意要是把let i放外面,两段代码一起执行就把下面的i改成j,否则let定义的变量名重了报错(Uncaught SyntaxError: Identifier ‘i’ has already been declared—未捕获语法错误:已声明标识符“i”)。var定义的变量是全局的,setTimeout执行时,for循环已经执行完,输出的i都指向同一个值5,所以输出5个5,但是let的定义的变量i,在每次for循环的时每个i都是在一个全新的作用域块中,输出的i指向的是不同作用域的i,不是同一个i,输出的值就不一样。

扩展:
要想for(var i=0;i<5;i++),也输出:0,1,2,3,4,可以使用闭包保存变量

for(var i=0;i<5;i++){
   (function(i){
    setTimeout(function(){
    console.log(i)
  },100)
   })(i);
}

3、未完待续,持续更新中。。。

猜你喜欢

转载自blog.csdn.net/qq_45989931/article/details/127246160