2021大厂前端面试核心面试题详解一 (1)

2021大厂前端面试核心面试题详解

一.说一下工作中解决过比较困难的问题,说一下自己项目中比较有亮点的地方

面试官看一下你解决问题的能力
平时要整理需求以及解决方案的笔记!

二.你了解浏览器的事件循环吗?

2.1 为什么js在浏览器中有事件循环机制吗?

  • JS是单线程的
  • 所以通过 event loop 这个概念,来实现了一些非阻塞的实现

2.2 你了解事件循环中有两种任务吗?

  • 宏任务:整体代码,setTimeOut,setInterval,node中的I/O操作…
  • 微任务:new Promise().then 里面的回调,MutationObserve(前端的回溯)

2.3 为什么要有微任务的概念?只有宏任务可以吗?

在JS的执行过程中,或者说页面的渲染过程中,他们所有的任务都是保持着先进先出的原则

  • 宏任务 先进先出的原则执行,不能准确控制这些事件被添加到整个任务队列里的位置,只是完全遵循先进先出;但是有了高优先级任务要处理,所以只有宏任务是不行的

  • 所以引入了微任务的概念,当我们有一个微任务,在浏览器里其实是,宏任务执行完一遍,就去微任务的队列里,把已存在的微任务执行一遍

  • 具体的机制:

    • 在整体的一个宏任务执行完一遍之后,那么会把它中途碰到的微任务已经添加到队列里面去了;

    • 然后宏任务执行完之后,会去微任务的队列里面,把已经添加进去的微任务执行一遍;

    • 当然,如果在微任务队列里面,又碰到了新添加的微任务,那么会继续执行微任务,直到把它执行完成;

    • 最后再去执行下一个宏任务,这就是浏览器里的事件循环

2.4 你了解node中的事件循环吗?和浏览器中的事件循环有什么区别呢?

  • 宏任务的执行顺序
    1.timers定时器:执行已经安排的 setTimeOut 和 setInterval 的回调

    setTimeOut(()=>{
      // 这里的内容xxx
    },3000)
    

    2.pending, callback 待定回调: 执行延迟到下一个循环迭代的I/O回调
    3.idle,prepare: 仅系统内部使用
    4.poll轮询:检索新的I/O事件,执行与I/O相关的回调
    5.check:执行setImmediate()回调函数
    6.close callbacks: socket.on(‘close’,()=>{})

  • 微任务和宏任务在node的执行顺序

    • Node v10及以前:
      1.执行完一个阶段中的所有任务
      2.执行nextTick队列里的内容
      3.执行完微任务队列里的内容
    • Node V10以后:
      和浏览器行为统一了
/* 第一题 */
async function async1(){
  console.log('async1 start');
  await async2() 
  // 理解成
  // await 关键字的意思:其实是把描述的函数 async(),放入new Promise里面,把这句话后面的都放到.then()里面
  // new Promise(()=>{
  //   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 ');

// 思路:先执行宏任务-整体代码块,再去执行微任务,再去执行宏任务。
// 每一个setTimeout都是一个新的宏任务,并不会合并,会被依次放到宏任务队列

// 我认为的 ===>>>> 嘿嘿,答对了~
// script start 
// async1 start
// async2
// promise1
// script end

// async1 end
// promise2
// setTimeOut
/* 第二题 */
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') // resolve被延迟执行
  }, 0);
}).then((res)=>{
  // !!!微任务的 .then()是如何出现的?
  // 在Promise里面,一定要resolve出去,这个Promise一定要有结果,这个微任务回调才会被添加到微任务队列里
  // 所以,第一轮宏任务执行过程中,并没有被添加到微任务队列里!!!
  console.log('children7'); 
  setTimeout(() => {
    console.log(res);
  }, 0);
})

// 我认为的 ===>>>> 达咩X,答错了
// start
// children4
// children3
// children7
// children2
// children5
// children6


/* 正确的 */
// start
// children4
// 第一轮宏任务结束,尝试清空微任务队列,发现没有微任务
// !!!但是在第一轮宏任务执行过程中,并没有返回结果
// children2 ,此时将children3放入微任务队列
// 第二轮宏任务结束,尝试清空微任务队列,发现有微任务
// children3
// 微任务结束
// children5, 此时把.then(res=>{
//   console.log('children7'); 
//   setTimeout(() => {
//     console.log(res);
//   }, 0);
// }) 放到了微任务里面
// 第三轮宏任务结束,尝试清空微任务队列,发现有微任务
// children7
// children6
/* 第三题 */
const p = function (){
  return new Promise((resolve,reject)=>{
    const p1 = new Promise((resolve,reject)=>{
      setTimeout(() => {
        resolve(1)
      }, 0);
      resolve(2) // 当前 Promise的状态已经结束了,已经输出了一个结果2,所以1就没了
    })
    p1.then(res=>{
      console.log(res);
    })
    console.log(3);
    resolve(4)
  })
}

p().then(res=>{
  console.log(res);
})

console.log('end');


// 我认为的 ===>>>> 嘿嘿,答对了~
// 3
// end
// 2
// 4
/* 第三题 变 */
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
// 4
// 1

你可能感兴趣的:(前端面试,javascript,面试,前端)