https://juejin.cn/post/6995334897065787422

ES6

1、let 和 const

这两个的出现,总感觉是为了开发的代码规范而出现的。我们要逐渐放弃var,在项目中多用let和const
与var的区别:

  • var有变量提升,有初始化提升,值可变
  • let有变量提升,没有初始化提升,值可变
  • const有变量提升,没有初始化提升,值不可变,但如果是定义对象,则属性可变

暂时性死区问题说明:其实let和const是有变量提升的,但是没有初始化提升:

  1. var name = '林三心'
  2. function fn () {
  3. console.log(name)
  4. let name = 'sunshin_lin'
  5. }
  6. fn() // Cannot access 'name' before initialization

块级作用域解决问题:

  1. for(var i = 0; i < 5; i++) {
  2. setTimeout(() => {
  3. console.log(i)
  4. })
  5. } // 5 5 5 5 5
  6. for(let i = 0; i < 5; i++) {
  7. setTimeout(() => {
  8. console.log(i)
  9. })
  10. } // 0 1 2 3 4

2、默认参数

开发中你曾遇到过这样的问题,如果参数不传进来,你就设置默认参数

  1. function fn (name, age) {
  2. var name = name || '林三心'
  3. var age = age || 18
  4. console.log(name, age)
  5. }
  6. fn() // 林三心 18

但是这么写确实不优雅,可以使用ES6的默认参数

  1. function fn (name = '林三心', age = 18) {
  2. console.log(name, age)
  3. }
  4. fn() // 林三心 18
  5. fn('sunshine', 22) // sunshine 22

3、扩展运算符

曾经的我,想要拼接多个数组,我只能这么做

  1. const arr1 = [1, 2, 4]
  2. const arr2 = [4, 5, 7]
  3. const arr3 = [7, 8, 9]
  4. const arr = arr1.concat(arr2).concat(arr3)
  5. [
  6. 1, 2, 4, 4, 5,
  7. 7, 7, 8, 9
  8. ]

现在的我,可以更优雅地进行拼接

  1. const arr1 = [1, 2, 4]
  2. const arr2 = [4, 5, 7]
  3. const arr3 = [7, 8, 9]
  4. const arr = [...arr1, ...arr2, ...arr3]
  5. [
  6. 1, 2, 4, 4, 5,
  7. 7, 7, 8, 9
  8. ]

4、剩余参数

大家可能遇到过这种问题,一个函数,传入参数的个数是不确定的,这就可以用ES6的剩余参数

  1. function fn (name, ...params) {
  2. console.log(name)
  3. console.log(params)
  4. }
  5. fn ('林三心', 1, 2) // 林三心 [ 1, 2 ]
  6. fn ('林三心', 1, 2, 3, 4, 5) // 林三心 [ 1, 2, 3, 4, 5 ]

5、模板字符串

以前的我,拼接字符串只能这么做

  1. const name = '林三心'
  2. const age = '22'
  3. console.log(name + '今年' + age + '岁啦') // 林三心今年22岁啦

现在我可以这么做,会更优雅

  1. const name = '林三心'
  2. const age = '22'
  3. console.log(`${name}今年${age}岁啦`) // 林三心今年22岁啦

6、Object.keys

可以用来获取对象的key的集合,进而可以获得对应key的value

  1. const obj = {
  2. name: '林三心',
  3. age: 22,
  4. gender: '男'
  5. }
  6. const keys = Object.keys(obj)
  7. console.log(keys) // [ 'name', 'age', 'gender' ]

7、箭头函数

以前我们使用普通函数

  1. function fn () {}
  2. const fn = function () {}

ES6新加了箭头函数

  1. const fn = () => {}
  2. // 如果只有一个参数,可以省略括号
  3. const fn = name => {}
  4. // 如果函数体里只有一句return
  5. const fn = name => {
  6. return 2 * name
  7. }
  8. // 可简写为
  9. const fn = name => 2 * name
  10. // 如果返回的是对象
  11. const fn = name => ({ name: name })

普通函数和箭头函数的区别:

  • 1、箭头函数不可作为构造函数,不能使用new
  • 2、箭头函数没有自己的this
  • 3、箭头函数没有arguments对象
  • 4、箭头函数没有原型对象

8、Array.forEach

ES6新加的数组遍历方法

  1. const eachArr = [1, 2, 3, 4, 5]
  2. // 三个参数:遍历项 索引 数组本身
  3. // 配合箭头函数
  4. eachArr.forEach((item, index, arr) => {
  5. console.log(item, index, arr)
  6. })
  7. 1 0 [ 1, 2, 3, 4, 5 ]
  8. 2 1 [ 1, 2, 3, 4, 5 ]
  9. 3 2 [ 1, 2, 3, 4, 5 ]
  10. 4 3 [ 1, 2, 3, 4, 5 ]
  11. 5 4 [ 1, 2, 3, 4, 5 ]

9、Array.map

常用于返回一个处理过后的新数组

  1. const mapArr = [1, 2, 3, 4, 5]
  2. // 三个参数:遍历项 索引 数组本身
  3. // 配合箭头函数,对每一个元素进行翻倍
  4. const mapArr2 = mapArr.map((num, index, arr) => 2 * num)
  5. console.log(mapArr2)
  6. [ 2, 4, 6, 8, 10 ]

10、Array.filter

顾名思义,用来过滤的方法

  1. const filterArr = [1, 2, 3, 4, 5]
  2. // 三个参数:遍历项 索引 数组本身
  3. // 配合箭头函数,返回大于3的集合
  4. const filterArr2 = filterArr.filter((num, index, arr) => num > 3)
  5. console.log(filterArr2)
  6. [ 4, 5 ]

11、Array.some

some,意思就是只有一个是真,那就返回真

  1. const someArr = [false, true, false, true, false]
  2. // 三个参数:遍历项 索引 数组本身
  3. // 配合箭头函数,只要有一个为true,就返回true,一个都true都没有,就返回false
  4. const someArr2 = someArr.some((bol, index, arr) => bol)
  5. console.log(someArr2)
  6. true

12、Array.every

every跟some是相反的,some是只有一个就行,every是要所有为真才返回真

  1. const everyArr = [false, true, false, true, false]
  2. // 三个参数:遍历项 索引 数组本身
  3. // 配合箭头函数,需要所有为true,才返回true,否则返回false
  4. const everyArr2 = everyArr.every((bol, index, arr) => bol)
  5. console.log(everyArr2)

13、Array.reduce

  • 第一个参数callback函数: pre为上次return的值,next为数组的本次遍历的项
  • 第二个参数为初始值,也是第一个pre

举两个例子:

  1. // 计算 1 + 2 + 3 + 4 + 5
  2. const reduceArr = [1, 2, 3, 4, 5]
  3. const sum = reduceArr.reduce((pre, next) => {
  4. return pre + next
  5. }, 0)
  6. console.log(sum) // 15
  7. // 统计元素出现个数
  8. const nameArr = ['林三心', 'sunshine_lin', '林三心', '林三心', '科比']
  9. const totalObj = nameArr.reduce((pre, next) => {
  10. if (pre[next]) {
  11. pre[next]++
  12. } else {
  13. pre[next] = 1
  14. }
  15. return pre
  16. }, {})
  17. console.log(totalObj) // { '林三心': 3, sunshine_lin: 1, '科比': 1 }

14、对象属性同名简写

以前同名属性需要这么写

  1. const name = '林三心'
  2. const age = '22'
  3. const obj = {
  4. name: name,
  5. age: age
  6. }
  7. console.log(obj) // { name: '林三心', age: '22' }

ES6新增语法,只需这么写

  1. const name = '林三心'
  2. const age = '22'
  3. // 属性同名可简写
  4. const obj = {
  5. name
  6. age
  7. }
  8. console.log(obj) // { name: '林三心', age: '22' }

15、Promise

Promise,中文名为承诺,承诺在哪呢?承诺在,一旦他的状态改变,就不会再改。这里就介绍基本使用,如果想要深入理解如何使用,请看我的另一篇文章看了就会,手写Promise原理,最通俗易懂的版本!!!
看看基本使用

  • 成功状态
  1. function requestData () {
  2. // 模拟请求
  3. return new Promise((resolve, reject) => {
  4. setTimeout(() => {
  5. resolve('林三心')
  6. }, 1000)
  7. })
  8. }
  9. requestData().then(res => {
  10. console.log(res) // 一秒钟后输出 '林三心'
  11. }, err => {
  12. console.log(err)
  13. })
  • 失败状态
  1. function requestData () {
  2. // 模拟请求
  3. return new Promise((resolve, reject) => {
  4. setTimeout(() => {
  5. reject('错误啦')
  6. }, 1000)
  7. })
  8. }
  9. requestData().then(res => {
  10. console.log(res)
  11. }, err => {
  12. console.log(err) // 一秒钟后输出 '错误啦'
  13. })
  • all方法
    • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
    • 如果所有Promise都成功,则返回成功结果数组
    • 如果有一个Promise失败,则返回这个失败结果
  1. // 如果全都为成功
  2. function fn(time) {
  3. return new Promise((resolve, reject) => {
  4. console.log(88)
  5. setTimeout(() => {
  6. resolve(`${time}毫秒后我成功啦!!!`)
  7. }, time)
  8. })
  9. }
  10. Promise.all([fn(2000), fn(3000), fn(1000)]).then(res => {
  11. // 3秒后输出 [ '2000毫秒后我成功啦!!!', '3000毫秒后我成功啦!!!', '1000毫秒后我成功啦!!!' ]
  12. console.log(res)
  13. }, err => {
  14. console.log(err)
  15. })
  16. // 如果有一个失败
  17. function fn(time, isResolve) {
  18. return new Promise((resolve, reject) => {
  19. setTimeout(() => {
  20. isResolve ? resolve(`${time}毫秒后我成功啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
  21. }, time)
  22. })
  23. }
  24. Promise.all([fn(2000, true), fn(3000), fn(1000, true)]).then(res => {
  25. console.log(res)
  26. }, err => {
  27. console.log(err) // 3秒后输出 '3000毫秒后我失败啦!!!'
  28. })
  • race方法
    • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
    • 哪个Promise最快得到结果,就返回那个结果,无论成功失败
  1. function fn(time, isResolve) {
  2. return new Promise((resolve, reject) => {
  3. setTimeout(() => {
  4. isResolve ? resolve(`${time}毫秒后我成功啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
  5. }, time)
  6. })
  7. }
  8. Promise.race([fn(2000, true), fn(3000), fn(1000)]).then(res => {
  9. console.log(res)
  10. }, err => {
  11. console.log(err) // 1秒后输出
  12. })

16、class

以前咱们使用构造函数生成对象,这么做

  1. function Person(name) {
  2. this.name = name
  3. }
  4. Person.prototype.sayName = function () {
  5. console.log(this.name)
  6. }
  7. const kobe = new Person('科比')
  8. kobe.sayName() // 科比

而有了ES6的class可以这么做

  1. class Person {
  2. constructor(name) {
  3. // 构造器
  4. this.name = name
  5. }
  6. sayName() {
  7. console.log(this.name)
  8. }
  9. }
  10. const kobe = new Person('科比')
  11. kobe.sayName() // 科比

值得一提的是,class本质也是functionclassfunction语法糖

  1. class Person {}
  2. console.log(typeof Person) // function
  3. ```js
  4. 除了以上,还需要知道class的以下知识点
  5. 静态属性和静态方法,使用`static`定义的属性和方法只能class自己用,实例用不了
  6. ```js
  7. class Person {
  8. constructor(name) {
  9. this.name = name
  10. }
  11. static age = 22
  12. static fn() {
  13. console.log('哈哈')
  14. }
  15. }
  16. console.log(Person.age) // 22
  17. Person.fn() // 哈哈
  18. const sunshine_lin = new Person('林三心')
  19. console.log(sunshine_lin.age) // undefined
  20. sunshine_lin.fn() // fn is not a function

extend继承

  1. class Animal {
  2. constructor(name, age) {
  3. this.name = name
  4. this.age = age
  5. }
  6. }
  7. class Cat extends Animal {
  8. say() {
  9. console.log(this.name, this.age)
  10. }
  11. }
  12. const cat = new Cat('ketty', 5) // 继承了Animal的构造器
  13. cat.say() // ketty 5

17、解构赋值

以前想提取对象里的属性需要这么做

  1. const obj = {
  2. name: '林三心',
  3. age: 22,
  4. gender: '男'
  5. }
  6. const name = obj.name
  7. const age = obj.age
  8. const gender = obj.gender
  9. console.log(name, age, gender) // 林三心 22 男

ES6新增了解构赋值的语法

  1. const obj = {
  2. name: '林三心',
  3. age: 22,
  4. gender: '男',
  5. doing: {
  6. morning: '摸鱼',
  7. afternoon: '摸鱼',
  8. evening: 'sleep'
  9. }
  10. }
  11. const { name, age, gender } = obj
  12. console.log(name, age, gender) // 林三心 22 男
  13. // 解构重名
  14. const { name: myname } = obj
  15. console.log(myname) // 林三心
  16. // 嵌套解构
  17. const { doing: { evening } } = obj
  18. console.log(evening) // sleep

也可以进行数组的解构

  1. const arr = [1, 2, 3]
  2. const [a, b, c] = arr
  3. console.log(a, b, c) // 1 2 3
  4. // 默认赋值
  5. const [a, b, c, d = 5] = arr
  6. console.log(a, b, c, d) // 1 2 3 5
  7. // 乱序解构
  8. const { 1: a, 0: b, 2: c } = arr
  9. console.log(a, b, c) // 2 1 3

18、find 和 findIndex

  • find:找到返回被找元素,找不到返回undefined
  • findIndex:找到返回被找元素索引,找不到返回-1
  1. const findArr = [
  2. { name: '科比', no: '24' },
  3. { name: '罗斯', no: '1' },
  4. { name: '利拉德', no: '0' }
  5. ]
  6. const kobe = findArr.find(({ name }) => name === '科比')
  7. const kobeIndex = findArr.findIndex(({ name }) => name === '科比')
  8. console.log(kobe) // { name: '科比', no: '24' }
  9. console.log(kobeIndex) // 0

19、for of 和 for in

  • for in :遍历方法,可遍历对象和数组
  • for of :遍历方法,只能遍历数组,不能遍历对象

先看for in:

  1. const obj = { name: '林三心', age: 22, gender: '男' }
  2. const arr = [1, 2, 3, 4, 5]
  3. for(let key in obj) {
  4. console.log(key)
  5. }
  6. name
  7. age
  8. gender
  9. for(let index in arr) {
  10. console.log(index)
  11. }
  12. 0 1 2 3 4

再看 for of:

  1. for(let item of arr) {
  2. console.log(item)
  3. }
  4. 1 2 3 4 5

20、Set 和 Map

  • Set

先说说Set的基本用法

  1. // 可不传数组
  2. const set1 = new Set()
  3. set1.add(1)
  4. set1.add(2)
  5. console.log(set1) // Set(2) { 1, 2 }
  6. // 也可传数组
  7. const set2 = new Set([1, 2, 3])
  8. // 增加元素 使用 add
  9. set2.add(4)
  10. set2.add('林三心')
  11. console.log(set2) // Set(5) { 1, 2, 3, 4, '林三心' }
  12. // 是否含有某个元素 使用 has
  13. console.log(set2.has(2)) // true
  14. // 查看长度 使用 size
  15. console.log(set2.size) // 5
  16. // 删除元素 使用 delete
  17. set2.delete(2)
  18. console.log(set2) // Set(4) { 1, 3, 4, '林三心' }

再说说Set的不重复性

  1. // 增加一个已有元素,则增加无效,会被自动去重
  2. const set1 = new Set([1])
  3. set1.add(1)
  4. console.log(set1) // Set(1) { 1 }
  5. // 传入的数组中有重复项,会自动去重
  6. const set2 = new Set([1, 2, '林三心', 3, 3, '林三心'])
  7. console.log(set2) // Set(4) { 1, 2, '林三心', 3 }

Set的不重复性中,要注意引用数据类型和NaN

  1. // 两个对象都是不用的指针,所以没法去重
  2. const set1 = new Set([1, {name: '林三心'}, 2, {name: '林三心'}])
  3. console.log(set1) // Set(4) { 1, { name: '林三心' }, 2, { name: '林三心' } }
  4. // 如果是两个对象是同一指针,则能去重
  5. const obj = {name: '林三心'}
  6. const set2 = new Set([1, obj, 2, obj])
  7. console.log(set2) // Set(3) { 1, { name: '林三心' }, 2 }
  8. 咱们都知道 NaN !== NaNNaN是自身不等于自身的,但是在Set中他还是会被去重
  9. const set = new Set([1, NaN, 1, NaN])
  10. console.log(set) // Set(2) { 1, NaN }

利用Set的不重复性,可以实现数组去重

  1. const arr = [1, 2, 3, 4, 4, 5, 5, 66, 9, 1]
  2. // Set可利用扩展运算符转为数组哦
  3. const quchongArr = [...new Set(arr)]
  4. console.log(quchongArr) // [1, 2, 3, 4, 5, 66, 9]
  • Map

Map对比object最大的好处就是,key不受类型限制

  1. // 定义map
  2. const map1 = new Map()
  3. // 新增键值对 使用 set(key, value)
  4. map1.set(true, 1)
  5. map1.set(1, 2)
  6. map1.set('哈哈', '嘻嘻嘻')
  7. console.log(map1) // Map(3) { true => 1, 1 => 2, '哈哈' => '嘻嘻嘻' }
  8. // 判断map是否含有某个key 使用 has(key)
  9. console.log(map1.has('哈哈')) // true
  10. // 获取map中某个key对应的value 使用 get(key)
  11. console.log(map1.get(true)) // 2
  12. // 删除map中某个键值对 使用 delete(key)
  13. map1.delete('哈哈')
  14. console.log(map1) // Map(2) { true => 1, 1 => 2 }
  15. // 定义map,也可传入键值对数组集合
  16. const map2 = new Map([[true, 1], [1, 2], ['哈哈', '嘻嘻嘻']])
  17. console.log(map2) // Map(3) { true => 1, 1 => 2, '哈哈' => '嘻嘻嘻' }

ES7

21、includes

传入元素,如果数组中能找到此元素,则返回true,否则返回false

  1. const includeArr = [1, 2 , 3, '林三心', '科比']
  2. const isKobe = includeArr.includes('科比')
  3. console.log(isKobe) // true

跟indexOf很像,但还是有区别的

  1. const arr = [1, 2, NaN]
  2. console.log(arr.indexOf(NaN)) // -1 indexOf找不到NaN
  3. console.log(arr.includes(NaN)) // true includes能找到NaN

22、求幂运算符

以前求幂,我们需要这么写

  1. const num = Math.pow(3, 2) // 9

ES7提供了求幂运算符:**

  1. const num = 3 ** 2 // 9

ES8

23、Object.values

可以用来获取对象的value的集合

  1. const obj = {
  2. name: '林三心',
  3. age: 22,
  4. gender: '男'
  5. }
  6. const values = Object.values(obj)
  7. console.log(values) // [ '林三心', 22, '男' ]

24、Object.entries

可以用来获取对象的键值对集合

  1. const obj = {
  2. name: '林三心',
  3. age: 22,
  4. gender: '男'
  5. }
  6. const entries = Object.entries(obj)
  7. console.log(entries)
  8. // [ [ 'name', '林三心' ], [ 'age', 22 ], [ 'gender', '男' ] ]

25、async/await

这个是很常用的语法了,我的理解就是:以同步方式执行异步操作
我们平时可能会遇到这种场景,接口一,请求到数据一,而数据一被当做请求二的参数去请求数据二,我们会用Promise这么做

  1. function fn() {
  2. // 模拟第一次请求
  3. return new Promise((resolve, reject) => {
  4. setTimeout(() => {
  5. resolve(5)
  6. }, 1000)
  7. }).then(res => {
  8. // 模拟第二次请求
  9. new Promise((resolve, reject) => {
  10. setTimeout(() => {
  11. // 拿第一次请求的数据去乘10,当做第二次请求的数据
  12. resolve(res * 10)
  13. }, 2000)
  14. }).then(sres => {
  15. console.log(sres)
  16. })
  17. })
  18. }
  19. fn() // 1 + 2 = 3 3秒后输出 50

这样的嵌套是不美观的,如果有很多个接口,那就会嵌套很多层,此时我们可以使用async/await来以同步方式执行异步,注意以下几点:

  • await只能在async函数里使用
  • await后面最好接Promise,如果后面接的是普通函数则会直接执行
  • async函数返回的是一个Promise
  1. function fn1 () {
  2. return new Promise((resolve, reject) => {
  3. setTimeout(() => {
  4. resolve(5)
  5. }, 1000)
  6. })
  7. }
  8. function fn2 (data) {
  9. return new Promise((resolve, reject) => {
  10. setTimeout(() => {
  11. resolve(data * 10)
  12. }, 2000)
  13. })
  14. }
  15. async function req () {
  16. // 同步方式执行异步,像排队一样
  17. const data1 = await fn1() // 等待1秒后返回数据再往下执行
  18. const data2 = await fn2(data1) // 拿data1去请求2秒后,往下走
  19. console.log(data2) // 总共3秒后 输出 50
  20. }
  21. req()

ES9

26、for await of

我们来看以下场景哈

  1. function fn (time) {
  2. return new Promise((resolve, reject) => {
  3. setTimeout(() => {
  4. resolve(`${time}毫秒后我成功啦!!!`)
  5. }, time)
  6. })
  7. }
  8. fn(3000).then(res => console.log(res))
  9. fn(1000).then(res => console.log(res))
  10. fn(2000).then(res => console.log(res))
  11. 结果是
  12. 1000毫秒后我成功啦!!!
  13. 2000毫秒后我成功啦!!!
  14. 3000毫秒后我成功啦!!!

但是我想要这个结果

  1. 3000毫秒后我成功啦!!!
  2. 1000毫秒后我成功啦!!!
  3. 2000毫秒后我成功啦!!!

第一时间我们肯定想到的是async/await

  1. function fn (time) {
  2. return new Promise((resolve, reject) => {
  3. setTimeout(() => {
  4. resolve(`${time}毫秒后我成功啦!!!`)
  5. }, time)
  6. })
  7. }
  8. async function asyncFn () {
  9. // 排队
  10. const data1 = await fn(3000)
  11. console.log(data1) // 3秒后 3000毫秒后我成功啦!!!
  12. const data2 = await fn(1000)
  13. console.log(data2) // 再过1秒 1000毫秒后我成功啦!!!
  14. const data3 = await fn(2000)
  15. console.log(data3) // 再过2秒 2000毫秒后我成功啦!!!
  16. }

但是上面代码也是有缺点的,如果有几十个,那不是得写几十个await,有没有一种方法可以通过循环来输出呢?

  1. function fn (time) {
  2. return new Promise((resolve, reject) => {
  3. setTimeout(() => {
  4. resolve(`${time}毫秒后我成功啦!!!`)
  5. }, time)
  6. })
  7. }
  8. async function asyncFn () {
  9. const arr = [fn(3000), fn(1000), fn(1000), fn(2000), fn(500)]
  10. for await (let x of arr) {
  11. console.log(x)
  12. }
  13. }
  14. asyncFn()
  15. 3000毫秒后我成功啦!!!
  16. 1000毫秒后我成功啦!!!
  17. 1000毫秒后我成功啦!!!
  18. 2000毫秒后我成功啦!!!
  19. 500毫秒后我成功啦!!!

27、Promise.finally

新增的Promise方法,无论失败或者成功状态,都会执行这个函数

  1. // cheng
  2. new Promise((resolve, reject) => {
  3. resolve('成功喽')
  4. }).then(
  5. res => { console.log(res) },
  6. err => { console.log(err) }
  7. ).finally(() => { console.log('我是finally') })
  8. new Promise((resolve, reject) => {
  9. reject('失败喽')
  10. }).then(
  11. res => { console.log(res) },
  12. err => { console.log(err) }
  13. ).finally(() => { console.log('我是finally') })

ES10

28、Array.flat

有一个二维数组,我想让他变成一维数组:

  1. const arr = [1, 2, 3, [4, 5, 6]]
  2. console.log(arr.flat()) // [ 1, 2, 3, 4, 5, 6 ]

还可以传参数,参数为降维的次数

  1. const arr = [1, 2, 3, [4, 5, 6, [7, 8, 9]]]
  2. console.log(arr.flat(2))
  3. [
  4. 1, 2, 3, 4, 5,
  5. 6, 7, 8, 9
  6. ]

如果传的是一个无限大的数字,那么就实现了多维数组(无论几维)降为一维数组

  1. const arr = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12]]]]
  2. console.log(arr.flat(Infinity))
  3. [
  4. 1, 2, 3, 4, 5,
  5. 6, 7, 8, 9, 10,
  6. 11, 12
  7. ]

29、Array.flatMap

现在给你一个需求

  1. let arr = ["科比 詹姆斯 安东尼", "利拉德 罗斯 麦科勒姆"];

将上面数组转为

  1. [ '科比', '詹姆斯', '安东尼', '利拉德', '罗斯', '麦科勒姆' ]

第一时间想到map + flat

  1. console.log(arr.map(x => x.split(" ")).flat());
  2. // [ '科比', '詹姆斯', '安东尼', '利拉德', '罗斯', '麦科勒姆' ]

flatMap就是flat + map,一个方法顶两个

  1. console.log(arr.flatMap(x => x.split(" ")));
  2. // [ '科比', '詹姆斯', '安东尼', '利拉德', '罗斯', '麦科勒姆' ]

30、BigInt

BigInt是ES10新加的一种JavaScript数据类型,用来表示表示大于 2^53 - 1 的整数,2^53 - 1是ES10之前,JavaScript所能表示最大的数字

  1. const theBiggestInt = 9007199254740991n;
  2. const alsoHuge = BigInt(9007199254740991);
  3. // 9007199254740991n
  4. const hugeString = BigInt("9007199254740991");
  5. // 9007199254740991n
  6. const hugeHex = BigInt("0x1fffffffffffff");
  7. // 9007199254740991n
  8. const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111");
  9. // 9007199254740991n

哦对了,既然是JavaScript新的数据类型,那他的typeof是啥?

  1. const bigNum = BigInt(1728371927189372189739217)
  2. console.log(typeof bigNum) // bigint

所以以后面试官问你JavaScript有多少种数据类型,别傻傻答6种了,要答8种,把ES6的Symbol和ES10的BigInt也加上去

31、Object.fromEntries

前面ES8的Object.entries是把对象转成键值对数组,而Object.fromEntries则相反,是把键值对数组转为对象

  1. const arr = [
  2. ['name', '林三心'],
  3. ['age', 22],
  4. ['gender', '男']
  5. ]
  6. console.log(Object.fromEntries(arr)) // { name: '林三心', age: 22, gender: '男' }

他还有一个用处,就是把Map转为对象

  1. const map = new Map()
  2. map.set('name', '林三心')
  3. map.set('age', 22)
  4. map.set('gender', '男')
  5. console.log(map) // Map(3) { 'name' => '林三心', 'age' => 22, 'gender' => '男' }
  6. const obj = Object.fromEntries(map)
  7. console.log(obj) // { name: '林三心', age: 22, gender: '男' }

32、String.trimStart && String.trimEnd

咱们都知道JavaScript有个trim方法,可以清除字符串首尾的空格

  1. const str = ' 林三心 '
  2. console.log(str.trim()) // '林三心'

trimStart和trimEnd用来单独去除字符串的首和尾的空格

  1. const str = ' 林三心 '
  2. // 去除首部空格
  3. console.log(str.trimStart()) // '林三心 '
  4. // 去除尾部空格
  5. console.log(str.trimStart()) // ' 林三心'

ES11

33、Promise.allSettled

ES11新增的Promise的方法

  • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
  • 把每一个Promise的结果,集合成数组,返回
  1. function fn(time, isResolve) {
  2. return new Promise((resolve, reject) => {
  3. setTimeout(() => {
  4. isResolve ? resolve(`${time}毫秒后我成功啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
  5. }, time)
  6. })
  7. }
  8. Promise.allSettled([fn(2000, true), fn(3000), fn(1000)]).then(res => {
  9. console.log(res)
  10. // 3秒后输出
  11. [
  12. { status: 'fulfilled', value: '2000毫秒后我成功啦!!!' },
  13. { status: 'rejected', reason: '3000毫秒后我失败啦!!!' },
  14. { status: 'rejected', reason: '1000毫秒后我失败啦!!!' }
  15. ]
  16. })

34、?. 和 ??

  • 先说说?.,中文名为可选链

比如我们需要一个变量,是数组且有长度,才做某些操作

  1. const list = null
  2. // do something
  3. if (list && list.length) {
  4. // do something
  5. }
  6. // 使用可选链
  7. const list = null
  8. // do something
  9. if (list?.length) {
  10. // do something
  11. }

比如有一个对象,我要取一个可能不存在的值,甚至我们都不确定obj是否存在

  1. const obj = {
  2. cat: {
  3. name: '哈哈'
  4. }
  5. }
  6. const dog = obj && obj.dog && obj.dog.name // undefined
  7. // 可选链
  8. const obj = {
  9. cat: {
  10. name: '哈哈'
  11. }
  12. }
  13. const dog = obj?.dog?.name // undefined

比如有一个数组,我不确定它存不存在,存在的话就取索引为1的值

  1. const arr = null
  2. // do something
  3. const item = arr && arr[1]
  4. // 可选链
  5. const arr = null
  6. // do something
  7. const item = arr?.[1]

比如有一个函数,我们不确定它存不存在,存在的话就执行它

  1. const fn = null
  2. // do something
  3. const res = fn && fn()
  4. // 可选链
  5. const fn = null
  6. // do something
  7. const res = fn?.()
  • 再说说??,中文名为空位合并运算符

请看以下代码,咱们使用||运算符,只要左边是假值,就会返回右边的数据

  1. const a = 0 || '林三心' // 林三心
  2. const b = '' || '林三心' // 林三心
  3. const c = false || '林三心' // 林三心
  4. const d = undefined || '林三心' // 林三心
  5. const e = null || '林三心' // 林三心

??||最大的区别是,在??这,只有undefined和null才算假值

  1. const a = 0 ?? '林三心' // 0
  2. const b = '' ?? '林三心' // ''
  3. const c = false ?? '林三心' // false
  4. const d = undefined ?? '林三心' // 林三心
  5. const e = null ?? '林三心' // 林三心

ES12

35、Promise.any

E12新增的Promise的方法

  • 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
  • 如果有一个Promise成功,则返回这个成功结果
  • 如果所有Promise都失败,则报错
  1. // 当有成功的时候,返回最快那个成功
  2. function fn(time, isResolve) {
  3. return new Promise((resolve, reject) => {
  4. setTimeout(() => {
  5. isResolve ? resolve(`${time}毫秒后我成功啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
  6. }, time)
  7. })
  8. }
  9. Promise.any([fn(2000, true), fn(3000), fn(1000, true)]).then(res => {
  10. console.log(res) // 1秒后 输出 1000毫秒后我成功啦
  11. }, err => {
  12. console.log(err)
  13. })
  14. // 当全都失败时
  15. function fn(time, isResolve) {
  16. return new Promise((resolve, reject) => {
  17. setTimeout(() => {
  18. isResolve ? resolve(`${time}毫秒后我成功啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
  19. }, time)
  20. })
  21. }
  22. Promise.any([fn(2000), fn(3000), fn(1000)]).then(res => {
  23. console.log(res)
  24. }, err => {
  25. console.log(err) // 3秒后 报错 all Error
  26. })

36、数字分隔符

数字分隔符可以让你在定义长数字时,更加地一目了然

  1. const num = 1000000000
  2. // 使用数字分隔符
  3. const num = 1_000_000_000

37、||= 和 &&=

  1. 或等于(||=) a ||= b 等同于 a || (a = b);
  2. 且等于(&&=) a &&= b 等同于 a && (a = b);

不知道是ES几

38、对象动态属性

我们经常碰到这样的问题,无论是在微信小程序还是React中,我们需要根据某个条件去修改某个数据

  1. if (type === 'boy') {
  2. this.setData({
  3. boyName: name
  4. })
  5. } else if (type === 'girl') {
  6. this.setData({
  7. girlName: name
  8. })
  9. }

我也不知道这个新特性叫啥,我就自己取名叫属性动态属性哈哈哈

  1. this.setData({
  2. [`${type}Name`]: name
  3. })