ES6面试题总结---Babel、Promise、async/await、Iterator、ES6模块

157 阅读6分钟

ES6转化为ES5的原理--Babel

  • Parser解析:将ES6语法解析为AST抽象语法树,通过baylon插件完成
  • Transformer转换:AST语法通过配置的plugins和presets转换成新的AST语法,主要由babel-transform插件完成。plugins和presets通常在.babelrc文件中配置
  • Generator生成:将新的AST语法树对象再生成浏览器可以识别的ES5语法,主要由babel-generator插件完成

let、const

Set、Map

Set

Set是一种集合,是由一组唯一且无序的值组成,没有重复元素。是一种特殊的存储结构

Set常用的方法

//创建一个空的Set
let mySet = new Set()
// 创建一个包含元素的Set
let mySet1 = new Set([1,2,3,4])
// 添加元素
mySet.add(5)
// 删除元素
mySet.delete(1)
// 检查元素是否存在
console.log(mySet.has(1)) // true
// 将Set转位数组
let myArray = Array.from(mySet)

Map

Map是一种集合数据结构,用于存储键值对

WeakSet、WeakMap

垃圾回收机制

WeakSet

一种集合,其中的元素只能是对象和Symbol,这些对象是弱引用的。

WeakMap

一种键值对的集合,其中的键是弱引用的

Proxy、Reflect

Promise

juejin.cn/post/729624…

Promise是什么

Promise是ES6中提供异步编程的方案,可以将异步操作以同步操作的流程表达出来,避免层层嵌套的回调函数

Promise对象方法

Executor

Executor是在创建Promise时需要传入的一个回调函数,这个回调函数会被立即执行,并且传入两个参数:

new Promise((resplve,reject)=>{
  console.log('executor代码')
})
// 通常我们会在Executor中确认Promise状态
- 通过resolve,可以兑现Promise的状态---》(fulfilled)
- 通过reject,可以拒绝Promise的状态---》(reject)

⚠️状态被确定下来,Promise的状态就不会改变

  • 如果

then方法

  • then方法接受两个参数:
    • fulfilled的回调函数:当状态变成fulfilled时会回调的函数
    • reject的回调函数:当状态变成reject时回调的函数
const promise = new Promise((resolve,reject)=>{})
promise.then(res=>{
  cosnole.log('res',res)
}).catch(err=>{
  console.log('err',err)
})
  • then方法可以多次调用:(每次调用都可以传入对应的fulfilled回调,当Promise的状态变成fulfilled时,回调函数都会被执行)
  • then方法的返回值:(返回值是一个Promise,可以链式调用)
    • 当then方法中的回调函数本身在执行时,处于pending状态
    • 当then方法中的回调函数返回一个结果时,处于fulfilled状态,会将结果作为resolve的参数。若返回的结果是一个promise,会将新的Promise的状态决定then返回的Promise的状态
    • 当then方法抛出一个异常时,处于reject状态。

catch方法

  • catch方法可以被多次调用
  • catch方法的返回值

finally方法

无论Promise对象变成fulfilled还是reject状态,最终的代码都会执行

Promise类方法

resolve方法

reject方法

all方法

  • 当所有的Promise状态变成fulfilled状态时,新的Promise状态为fulfilled,并且会将所有Promise的返回值组成一个数组;

  • 当有一个Promise状态为reject时,新的Promise状态为reject,并且会将第一个reject的返回值作为参数

allSettled方法

  • 该方法会在所有的Promise都有结果,无论是fulfilled,还是reject时,都会有最终的状态。并且这个Promise的结果一定是fulfilled的

race方法

  • 多个Promise竞争,谁先有结果,就使用谁的结果

any方法

  • any方法会等到一个fulfilled状态,才会决定新Promise的状态
  • 若所有的Promise都是reject的,也会等到所有的Promise都变成rejected状态,结果会报错

async、await(通过同步的方式执行异步任务

使用async/await主要是避免传统的回调函数或者Promise链的嵌套 async内部代码同步执行 async函数返回一个Promise对象:(async函数内部return返回的值,会成为then方法回调函数的参数)

async function f(){
  return 'hello'
}
f().then((v=>{console.log(v)})) // hello

问题:100个请求,如何控制并发【并发最大数量为10】?

第一种:使用promise.all(但是如果有一个失败怎么办????)

有一个请求失败就无法获取该组其他成员的返回值

第二种:promise.allSettled()(如果有一个请求非常耗时,会出现什么情况???)

有一个慢接口的并发组返回会很慢,会导致其他的接口阻塞,并发时间变长

最佳方法:

  • 建一个运行池,一个等待队列,运行池中始终保持10个并发请求
  • 运行池中有一个请求完成,就从等待队列中拿出一个新请求放到运行池中,保证运行池始终是满负荷运行 juejin.cn/post/735026…

Iterator(迭代器)

定义

是一种接口机制,为不同的数据结构提供统一的访问机制。让不支持遍历的数据结构“可遍历”,主要供“for...of”消费

基础使用

它是一种接口,这个接口要求return一个对象,并且这个对象要有next函数,而且next函数需要return一个对象,这个对象要有value属性和down属性。

具有Iterator接口的数据结构有哪些?

  • Array、Map、Set、String、函数的arguments对象、NodeList对象 🌰:
function makeIterator(arr) { 
   let nextIndex = 0 
   return { 
     next() { 
       return nextIndex < arr.length ? { value: arr[nextIndex++], down: false } : { value: false, down: true } } 
       } 
} 
makeIterator(['a', 'b', 'c']) 
let it = makeIterator(['a', 'b', 'c']) 
console.log(it.next()); 
console.log(it.next()); 
console.log(it.next()); 
console.log(it.next());

image.png

🌰:遍历不可遍历的对象

let courses = {
  allCourse: {
    frontend:['ES6','Vue','React','小程序'],
    backend: ['Java','Go','Python','Spring boot'],
    webapp: ['Android','ios']
  }
}
for(let item of courses) {
  console.log(item);  //  报错,【non-array objects must have a [Symbol.iterator]() method】
}

改变不可遍历的对象进行迭代

对不可遍历的对象进行迭代,只需要满足两个协议就好:

  • 1:可迭代协议:当前对象上是否有[Symbol.iterator]属性,有可迭代,使用for...of遍历。没有不可迭代
  • 2:迭代器协议:当前的迭代器符合这种结构
return {
  next(){
    return {
      done,
      value
    }
  }
}

🌰:

let courses = {
  allCourse: {
    frontend:['ES6','Vue','React','小程序'],
    backend: ['Java','Go','Python','Spring boot'],
    webapp: ['Android','ios']
  }
}
courses[Symbol.iterator] = function (){
   let allCourse = this.allCourse
   let keys = Reflect.ownKeys(allCourse)
   let values = []
   return {
    next(){
      return {
        done:!values.length,
        value:values.shift()
      }
    }
   }
}
for(let item of courses){
  console.log(item)
}

itertor的使用场景(对象不可使用for..of遍历,使用Itertor接口重写对象)

多人合作开发中,对对象进行迭代,需要遍历时使用。

Module

CommonJS

模块定义和使用

在 Commonjs 中,一个文件就是一个模块。定义一个模块导出通过 exports 或者module.exports挂载即可。

exports.count = 1

导入一个模块也很简单,通过 require 对应模块拿到 exports 对象。

const counter = require('./counter')

ES6模块

CommonJS与ES6模块的区别

  • CommonJS模块输出的是一个值的拷贝,ES6 模块输出的是值的引用;
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
  • 在CommonJS顶层,this指向当前模块;而在ES6模块中,this指向undefinedimage.png