js有三个大问题:做用域,原型链,同异步node
同异步想要知道同异步问题就要找到js的运行机制:ajax
js是单线程:同一时间只能执行一件事情编程
浏览器是多线程:同一时间内能执行多件事情promise
为何js是单线程:假若有2个函数同时执行,一个是添加元素,一个是删除元素,浏览器就不知道该如何执行,因此js设计成了单线程浏览器
例如在浏览器中打开一个HTML页面的时候,就占用了一个进程,浏览器分配一个线程去计算DOM树,分配其余线程去加载对应的资源文件,再分配一个线程去自上而下执行js多线程
能够查看浏览器控制台的Network,有不少线程在进行异步
同步:在一个线程上(主栈 / 主任务队列)同一个时间只能作一件事情,当前事情完成才能进行下一个事情(先把一个任务进栈执行,执行完成,再进行下一个进栈,上一个任务出栈)async
异步:在主栈中执行一个任务,发现这个任务是异步的操做,会把异步操做移出主栈,放到等待任务队列中,这个时候浏览器会再分配其余线程监听异步任务是否到达指定的执行时间,等待主栈执行完,监听者会把到达时间的异步任务,从新放到主栈中执行异步编程
在js中,分为执行队列和等待队列,当遇到异步任务,会把该任务对应的回调函数放到等待队列中,当执行队列中执行完毕,再去等待列队查看知足条件的任务,把其对应的回调放到主任务队列中执行,主任务队列也叫执行栈函数
所谓js中的异步编程仅仅是根据某些机制来管控任务的执行顺序,不存在同时执行两个任务一说
在js中异步执行的有:setTimeout / set 、ajax 、事件绑定,回调函数,Promise(async / await)、node的process.nextTick、node的fs的I/O操做
setTimeOut(()=>{ console.log(1);//再输出1 },10) for(let i=0; i<1000; i++){//同步 } console.log(100); //先输出100
let xhr = new XMLHttpRequest();//第一步进栈new一个实例后再出栈 xhr.open('GET','XXX.JSON',false);//第二步进栈 执行open后再出栈,设置为同步 此时 readyState=1 xhr.onreadystatechange=function(){//此时进栈发现监听事件是异步,放等待任务中,此时 readyState=1;第四步当执行完send,readyState=4的时候 执行异步 console.log(xhr.readyState);//readyState=4 } xhr.send();//第三步执行 同步任务send ,此时readyState=4的时候主栈空闲
ajax开始是send开始,结束是状态为4结束
let xhr = new XMLHttpRequest();//第一步进栈new一个实例后再出栈 xhr.open('GET','XXX.JSON',false);//第二步进栈 执行open后再出栈,设置为同步 此时 readyState=1 xhr.send();//第三步执行 同步任务send ,此时readyState=4,结束 xhr.onreadystatechange=function(){//状态改变的时候才会触发监听,放等待队列的时候状态已是4了,不会再改变了,因此不会执行这个方法了 console.log(xhr.readyState);//一次都不输出 }
let xhr = new XMLHttpRequest();//第一步进栈new一个实例后再出栈 xhr.open('GET','XXX.JSON',true);//第二步进栈 执行open后再出栈,设置为异步 此时 readyState=1 xhr.send();//第三步执行 同步任务send ,会有一个线程是去请求数据,主栈空闲下来,此时readyState=1, //发现异步,放等待队列中,此时readyState=1 xhr.onreadystatechange=function(){//主栈空闲了,readyState变成2,函数执行一次, //状态为3的时候,又执行一次, //状态为4的时候,把函数又执行一次 console.log(xhr.readyState); //2,3,4 }
js事件:主线程不断的重复得到消息,执行消息,再取消息,再执行...事件循环
宏任务和微任务
主线程每次只能执行一个任务,当主线程执行完毕,会首先去微任务队列中去获取第一个执行任务,当把微任务中的任务队列中的任务执行完成,才去宏任务队列去寻找该执行的任务
宏任务:定时器,ajax,setImmendiate
微任务:promise的then,async await , process.nextTick
若是遇到了多个微任务,谁先放入谁先执行,微任务执行完毕,再去执行宏任务