JS运行机制

1.为什么JS是单线程的?
 
JS的单线程,与它的用途有关。
 
作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。
 
比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准
 
但是浏览器是多线程的
 
2.事件循环机制中的两种任务
 
宏任务:整体代码,setTimeout,setInterval等
 
微任务:new Promise ().then的回调,MutationObserver(前端回溯)用来监听事件的改变的
 
3.为什么要引入微任务的概念,只有宏任务不行吗
 
宏任务遵循先进先出的原则执行,但是如果在宏任务执行的过程中有了优先级更高的任务需要先执行,那么此时往任务队列中添加新任务的话,因为宏任务秉持着先进先出的原则,新添加的任务也只能是被排在后面的,那是万万不行的,所以才引入了微任务
 
4.事件循环
 
先执行同步,再执行异步,异步中先执行微任务再执行宏任务
 
首先,整体的js代码(作为第一个宏任务)开始执行的时候,会把所有代码分为同步任务、异步任务两部分,
 
同步任务会直接进入主线程依次执行,同步任务执行完后,执行异步任务,
 
异步任务会再分为宏任务和微任务,
 
微任务中先执行同步任务,异步任务依旧放到任务队列中排队,
 
当主线程空闲的时候,任务队列中异步任务再依次执行
 
上述过程会不断重复,这就是Event Loop,比较完整的事件循环
 
5.Promise
 
new Promise(() => {}).then()
 
敲黑板划重点——
 
前面的 new Promise() 这一部分是一个构造函数,这是一个同步任务
 
后面的 .then() 才是一个异步微任务
 
new Promise((resolve) => {
 
console.log(1)
 
  resolve()
 
}).then(()=>{
 
console.log(2)
 
})
 
console.log(3)
 
//上面代码输出1 3 2
 
6.async / await 
 
async/await本质上还是基于Promise的一些封装,而Promise是属于微任务的一种
 
所以在使用await关键字与Promise.then效果类似
 
setTimeout(() => console.log(4))
 
async function test() {
 
  console.log(1)
 
  await Promise.resolve()
 
  console.log(3)
 
}
 
test()
 
console.log(2)
 
//上述代码输出1 2 3 4
 
setTimeout(() => console.log(4))
 
async function test() {
 
  console.log(1)
 
  await async2()
 
  console.log(3)
 
 }
 
function async2() {
 
  console.log(5);
 
 }
 
test()
 
console.log(2)
 
//上述代码输出1 5 2 3 4
 
await 修饰的函数及以前的代码,相当于与 new Promise 的同步代码
 
await 以后的代码相当于 Promise.then的异步
 
7.附上几道面试题
 
function test() {
 
  console.log(1)
 
  setTimeout(function () { 
 
    console.log(2)
 
  }, 1000)
 
}
 
test();
 
setTimeout(function () {
 
  console.log(3)
 
})
 
new Promise(function (resolve) {
 
  console.log(4)
 
  setTimeout(function () {
 
    console.log(5)
 
  }, 100)
 
  resolve()
 
}).then(function () {
 
  setTimeout(function () {
 
    console.log(6)
 
  }, 0)
 
  console.log(7)
 
})
 
console.log(8)
 
//上述代码输出 1、4、8、7、3、6、5、2
 
    async function async1() {
 
      console.log(‘async1 start’);
 
      await async2();
 
      console.log(‘async1 end’);
 
    }
 
    async function async2() {
 
      console.log(‘async2’);
 
    }
 
    console.log(‘script start’);
 
    setTimeout(() => {
 
      console.log(‘setTimeout’);
 
    }, 0);
 
    async1();
 
    new Promise((resolve)=> {
 
      console.log(‘promise1’);
 
      resolve()
 
    }).then(()=> {
 
      console.log(‘promise2’);
 
    })
 
    console.log(‘script end’);
 
    //上述代码输出
 
    // ‘script start’
 
    //’async1 start’
 
    //’async2′
 
    //’promise1′
 
    //’script end’
 
    //’async1 end’
 
    //’promise2′
 
    //’setTimeout’
 
    //await async2();
 
    //相当于 new Promise((resolve) => {
 
        async2();
 
        resolve();
 
      }).then(() => { console.log(‘async1 end’) })
 
    console.log(‘start’);
 
    setTimeout(() => {
 
      console.log(‘children2’);
 
      Promise.resolve().then(() => {
 
        console.log(‘children3’);
 
      })
 
    }, 0);
 
    new Promise((resolve, reject) => {
 
      console.log(‘children4’);
 
      setTimeout(() => {
 
        console.log(‘children5’);
 
        resolve(‘children6’)
 
      }, 0);
 
    }).then(res => {
 
      console.log(‘children7’);
 
      setTimeout(() => {
 
        console.log(res);
 
      }, 0);
 
    })
 
    // 上述代码输出
 
    //’start’
 
    //’children4′
 
    //第一轮宏任务结束,发现没有微任务,原因:new Promise里并没有resolve(),只有resolve()才会把.then放到微任务里
 
    //’children2′
 
    //’children3′
 
    //’children5′
 
    //’children7′
 
    //’children6′
 
    const p = function () {
 
      return new Promise((resolve, reject) => {
 
        const p1 = new Promise((resolve, reject) => {
 
          setTimeout(() => {
 
            resolve(1)
 
          }, 0);
 
          resolve(2)
 
        })
 
        p1.then(res => {
 
          console.log(res);
 
        })
 
        console.log(3);
 
        resolve(4)
 
      })
 
    }
 
    p().then(res => {
 
      console.log(res);
 
    })
 
    console.log(‘end’);
 
    // 上述代码输出
 
    //3
 
    //end
 
    //Promise的状态是唯一且不可改变的,所有当resolve(2)的时候.then已经被输出了,setTimeout里的resolve(1)就没有了
 
    //2
 
    //4

如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h64385.shtml

张贴在3