1. javascript 这门语言设计之初就是为了解决用户在浏览器操作,浏览器可以响应用户在浏览器的操作。从而做出一些事情、比如用户在浏览器的输入框输入了自己的用户名、但是对于用户名的状态浏览器没有办法知道,得通过服务端的验证、才能判断、这样会浪费时间以及让用户等待、浏览器本身没有响应、为了解决类似的问题、javascript就产生了。
    既然说了javascript的产生那么就能肯定它是运行在浏览器的、没有编译、直接解释运行。
  2. javascript 是单线程模式、
    1. 在我们熟悉的谷歌浏览器有JavaScript的解释器我们称为v8引擎、其中这里指的单线程不是说js引擎是只有一个。
    在浏览器中有多个引擎来配合解析js代码、这里指的单线程是主线程:在主线程一次只能运行一个任务、其它的任务排队、依次执行。那么这个模式就会产生一个严重的问题、前面的任务运行太慢、以至于后面的任务只能等待、这样就导致延迟了程序的执行时间。导致页面没有响应。以及卡顿等一系列问题、为了解决这个问题js设计了事件驱动模式来执行js的代码、
事件驱动模式:事件驱动模式即把js代码划为为同步代码和异步代码。所有的同步代码都在主线程依次执行、异步代码
    会将其挂起、等主线程代码执行完、异步代码会进入一个任务队列、然后进入主线程执行、依次循环执行。

同步任务:同步任务指的是没有被js引擎挂起的代码、执行的时候会在主线程依次直接执行。
异步任务:js引擎遇到异步任务会将其挂起放到任务队列、等主线程同步任务执行完了然后再执行任务队列里的任务。既异步任务不会有阻塞的效果。

常见的异步任务:定时器、ajax请求、事件监听、
       1.定时器
         在遇到定时器代码的时候、js引擎会将其挂起、在谷歌浏览器有专门处理定时器的线程、那么会产生一个任务队列、专门放置定时器的异步代码、等到主线程的js代码执行完、js引擎会询问任务队列、此时任务队列有定时器的回调函数、那么就进入主线程变成同步任务执行、此时一次事件循环完毕、js代码执行完毕、如果有其它的异步任务、就再次进行上述操作、不断循环、所有的异步代码执行完成、程序也就执行完毕了。
   2.  ajax请求
         我们常见的ajax请求也是异步、在遇到ajax的代码、主线程也会将其挂起、在谷歌浏览器有专门处理ajax请求的 http线程、那么遇到它是会产生一个任务队列、将其回调函数放到任务队列、等所有同步代码执行完成、回过头再从任务队列中取出、然后在主线程变成同步任务来执行、后续就是不断循环这个操作、直到所有的异步代码执行完毕、程序就结束。
    3.事件监听
        在我们操作dom的时候、我们会给dom绑定事件、那么它的执行时机就取决于我们触发这个事件的时间、在谷歌浏览器有专门处理事件监听的线程、在遇到它是也会产生任务队列、将其放到任务队列、什么触发事件、就从任务队列取出、在主线程执行。
  1. js引擎执行代码的原理大体是如此、那么在实际我们遇到的代码是如何执行、以及他们的执行顺序。请看下面的例子:
async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
	console.log('async2');
}

console.log('script start');

setTimeout(function() {
    console.log('setTimeout');
}, 0)

async1();

new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');

上面代码的执行顺序为

// script start
 // async1 start
 // async2
 // promise1
 // script end
 // async1 end
 // promise2
 // setTimeout
console.log(1);
setTimeout(function(){
  console.log(2);
},300)
setTimeout(function(){
  console.log(3);
},200)
for(var i = 0;i<10000;i++){
  console.log(4);
}
setTimeout(function(){
  console.log(5);
},100)
console.log(1);
setTimeout(function(){
  console.log(2);
},300)
setTimeout(function(){
  console.log(3);
},200)
for(var i = 0;i<100;i++){
  console.log(4);
}
setTimeout(function(){
  console.log(5);
},100)

上面代码的执行顺序为:

// 1 (前)
 // 4(输出一万次)
 // 1 (后)
 //4(输出100次)
 // 3(前)
 //5(前)
 //5(后)
 //2(前)
 //3(后)
 //2(后)const foo = new Promise(resolve => {
    console.log(1);
    resolve();
    console.log(2);
})
foo.then(() => {
    console.log(3);
})
console.log(4);//顺序1,2,4,3