1. JS 事件轮询机制
JS 引擎主线程将所有 js 代码放入执行栈中依次执行,遇到同步代码从上到下依次执行。遇到异步代码,将任务交给浏览器分线程管理模块去执行,JS 引擎主线程会继续剩下代码
例如:
- JS 引擎主线程遇到定时器代码,交给浏览器定时器管理模块计时,当定时器到点,浏览器定时器管理模块会将回调函数放入宏任务队列等待执行
- JS 引擎主线程遇到 DOM 事件代码,交给浏览器 DOM 事件管理模块绑定事件,等用户触发事件,将回调函数放入宏任务队列等待执行
等 JS 引擎主线程执行完全局所有代码,此时就会开启事件轮询(event loop)
此时异步任务队列有两个:分别是宏任务队列和微任务队列
宏任务:
- 定时器(setTimeout/setInterval)
- DOM 事件
- ajax
微任务:
- Promise.then/catch/finally
- async await
- MutationObserver(监视 DOM 元素变化,一旦发生变化就会执行某个回调)
具体流程:
- 取出微任务队列中回调函数,依次执行
- 等微任务队列中回调函数全部执行完毕,取出宏任务队列中第一个回调函数,执行
- 等宏任务队列中第一个回调函数执行完毕,继续依次执行微任务队列中所有回调函数
- 等微任务队列中回调函数全部执行完毕,取出宏任务队列中下一个回调函数,执行
- 等宏任务队列中第一个回调函数执行完毕,继续依次执行微任务队列中所有回调函数
- 以此反复
2. Web Worker
- 概念
Web Worker 是 H5 新特性,允许我们开辟分线程,运行 js 代码。
- 使用
const worker = new Worker('./xxx.js')创建分线程执行 js 脚本- 主线程通过
worker.onmessage事件接受分线程的消息 - 主线程通过
worker.postMessage方法向分线程发送消息 - 分线程通过
self.onmessage事件接受主线程的消息 - 分线程通过
self.postMessage方法向主线程发送消息
- 应用
主要用于 js 中大量计算工作,比如大文件上传中计算文件的 hash,使用了 web worker
3. 说出 ES6 常用新语法
- 简单的语法
- const 与 let
- 解构赋值
- 形参默认值
- 扩展运算符: ...
- 模板字符串
- 模块化语法
- 对象的属性与方法简写
- 新的基本数据类型 Symbol
- 比较复杂的语法
- 箭头函数
- 箭头函数没有 arguments,需要使用 ...args 获取实参列表
- 箭头函数没有显示原型属性,不能被 new 调用
- 箭头函数编码更加简洁,还能简写:
- 参数只有一个,可以省略()
- 语句只有一条,可以省略{},这条语句会作为函数的返回值(默认加 return)
- 箭头函数没有自己的 this,它的 this 指向外层函数的 this
- 说到 this 指向,平时我专门总结过 this 指向
- ...(此处可以说 this 指向)
- promise
- promise + async & await 异步编程最终方案
- 都属于微任务 引导 js 事件循环机制
- Proxy(引申 vue2 和 vue3 响应式原理)
- Proxy 语法简介
- vue2 是通过 Object.defineProperty 实现的响应式,问题是新增数据不是响应式的
- vue3 是通过 Proxy 实现的响应式,解决了这个问题
- Map / Set / WeakMap / WeakSet (引申 vue3 响应式原理)
- 他们都是新的存储数据的结构
- Map 相当于对象,存储键值对,特点:key 可以是任意类型
- Set 相当于数组,特点:值是唯一的 数组去重:[...new Set(arr)]
- WeakMap 和 Map 相似,有两点不同:1. WeakMap 的 key 只能是对象类型 2. 一旦 key 对应的对象,外面没有引用,整个数据被垃圾回收机制回收
- WeakSet 和 Set 相似,有两点不同:1. WeakSet 的值只能是对象类型 2. 一旦值对应的对象,外面没有引用,整个数据被垃圾回收机制回收
- 还有 class 与 extends (拓展:原型、原型链、ES5继承)
- 主要用来做继承的,继承方案有:构造函数+原型继承,组合式继承,class&extends 继承
4. 说说 ES6 的 promise
- 概念
promise 是一个异步编程解决方案之一,用来解决异步回调地狱问题。
- promise 对象内部有 3 种状态
- pending 初始化状态
- resolved / fulfilled 成功状态
- rejected 失败状态
状态只能变化一次,只能有以下两种变化:
- pending --> resolved
- pending --> rejected
状态发生变化后不能在改了。
- 如何改变 promise 的状态
- 调用 resolve(), 改成成功状态
- 调用 reject(), 改为失败状态
- 生成一个 promise
new Promise()会生成 promise 实例对象,传入一个回调函数作为参数,回调函数有接收 resolve、reject 两个参数
它们用来改变 promise 对象状态的
- promise 实例对象上的方法
promise 实例对象上可以使用三个方法:then、catch、finally
- 当 promise 对象变成成功状态,触发 then 第一个回调
- 当 promise 对象变成失败状态,触发 catch 第一个回调
- 当 promise 对象不管变成成功还是失败状态,都会触发 finally 第一个回调
三个方法:then、catch、finally 都返回一个 promise 对象,所以 promise 可以链式调用
返回的 promise 状态:
- 如果报错了,返回失败状态
- 如果内部返回了 promise,就看这个 promise 的状态
- 如果没有发生上述情况,返回成功状态
- Promise 构造函数上的方法
- Promise.resolve() 一般返回一个成功的 promise,也有可能返回失败的 promise
- Promise.reject() 一定返回一个失败的 promise
- 二次封装 axios,响应拦截器使用了 Promise.reject()
- Promise.all([]) 所有 promise 对象成功才成功,只要有一个失败就失败
- Promise.allSettled() 不管成功或失败都能得到结果,成功得到成功结果,失败得到失败的原因
- 同时发送多个请求,可以使用 all 或 allSettled
- Promise.race() 返回第一个状态发生变化的 promise(不管成功/失败)
- 对某个请求做一个超时限制
- 面试题
- 需求 1:先请求 a、再请求 b、最后请求 c,怎么做? async await a() await b() await c()
- 需求 2:同时请求 a、b、c,怎么做?
Promise.all([a, b, c])
- 需求 3:Promise.all 一旦有一个失败了,就全失败了, 不太好(一个失败,其他白做了)
const result = await Promise.allSettled([a, b, c])
result.filter(item => item.status === 'fulfilled')
5. 谈谈模块化语法
- Commonjs 模块化语法
- 主要用于服务器端(Nodejs)
- 语法:
- 引入 require
- 自定义模块,模块路径必须以./或../开头
- 别人的默认,模块路径直接写模块名称即可
- 暴露 exports/module.exports
- 模块最终暴露的是 module.exports 指向的值
- 引入 require
- ES6 模块化语法
- 主要用于浏览器端
- 语法:
- 引入:import
- 暴露:export
- 总结
- 如果模块采用默认暴露:
import xxx from 'xxx' - 如果模块采用分别/统一暴露:
- 如果需要引入模块部分内容:
import { xxx } from 'xxx' - 如果需要引入模块全部内容:
import * as xxx from 'xxx'
- 如果需要引入模块部分内容:
- 如果模块采用默认暴露:
6. 谈谈箭头函数
- 箭头函数没有自己的 this,它的 this 指向外层函数的 this
- 箭头函数没有 arguments,需要使用 ...args 获取实参列表
- 箭头函数没有显示原型属性,不能被 new 调用
- 箭头函数编码更加简洁,还能简写:
- 参数只有一个,可以省略()
- 语句只有一条,可以省略{},这条语句会作为函数的返回值(默认加 return)
7. 浅度克隆和深度克隆
- 深浅克隆有什么区别?
- 浅克隆:基本类型克隆值,引用类型克隆地址值。
- 问题:源对象和克隆新对象的引用类型还是同一个地址,修改这个数据都会发生变化
- 深克隆:将所有值全都克隆新的,不会有上述问题
- 有哪些是浅克隆?
- Object.assign()
- arr.slice()
- [...arr]
- 有哪些是深克隆?
- JSON.parse(JSON.stringify(xxx)) : 函数、日期等类型没法克隆
- 自定义实现深克隆: 函数、日期等类型没法克隆
- lodash/cloneDeep