ES6~ES12知识梳理以及总结

1、let和const

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

与var的区别:

  • var有变量提升,有初始化提升,值可以变,var只有函数作用域
  • let有变量提升,没有初始值提升,值可以变
  • const有变量提升,没有初始化提升,值不可变。但如果是定义对象,则属性可变

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

var name='Amelian'
function fn(){
    console.log(name);
    let name = 'hzz'
}
fn()// Cannot access 'name' before initialization

2、默认参数

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

function(name,age){
    var name=name || 'Amelian';
    var age=age || 18;
    console.log(name,age);
}
fn()// 林三心 18

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

function fn(name='Amelian',age=18){
    console.log(name,age)
}

fn()// 林三心 18
fn('sunshine', 22) // sunshine 22

3、扩展运算符

在es6之前,想拼接多个数组,一般使用下面的操作:

const arr1=[1,2,4]
const arr2=[1,5,4]
const arr3=[1,8,4]

const arr=arr1.concat(arr2).concat(arr3)

有了es6之后,可以直接使用扩展运算符进行操作

const arr1=[1,2,4]
const arr2=[1,5,4]
const arr3=[1,8,4]

const arr=[...arr1,...arr2,...arr3]

4、剩余参数

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

function fn(name,...params){
    console.log(name);
    console.log(params)
}

fn('Amelian',1,2) // Amelian [ 1, 2 ]
fn('Amelian',1,2,3,4,5) // Amelian [ 1, 2, 3, 4, 5 ]

5、模板字符串

以前,凭借字符串只能这么做:

const name='Amelian'
const age=22

console.log(name+'今年'+age+'岁啦')// // Amelian今年22岁啦

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

const name='Amelian'
const age=22

console.log(`${name}今年${age}岁啦`)// // Amelian今年22岁啦

6.Object.keys

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

扫描二维码关注公众号,回复: 15103834 查看本文章
const obj={
    name:'Amelain',
    age:18,
    gender:'女'

}

const keys=Object.keys(obj)
console.log(keys)//['name','age','gender']

7、箭头函数

在es6之前都是使用普通函数

function fn(){}
const fn=function(){}

es6新加了箭头函数

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

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

8、Array.prototype.foreach(数组遍历的方法)

const eachArr=[1,2,3,4,5]
//三个参数:遍历项、索引、数组本身
//配合箭头函数
eachArr.forEach((item,index,arr)=>{

    console.log(item,index,arr)
})
1 0 [ 1, 2, 3, 4, 5 ]
2 1 [ 1, 2, 3, 4, 5 ]
3 2 [ 1, 2, 3, 4, 5 ]
4 3 [ 1, 2, 3, 4, 5 ]
5 4 [ 1, 2, 3, 4, 5 ]

9、Array.prototype.map(循环遍历,返回新的数组)

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

const mapArr=[1,2,3,4,5]

//三个参数:遍历项、索引、数组本身
//配合箭头函数,对每个元素进行翻倍

const mapArr2=mapArr.map((num,index,arr)=>{
    return 2*num
})
console.log(mapArr2)

[ 2, 4, 6, 8, 10 ]

10、Array.prototype.filter

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

const filterArr=[1,2,3,4,5,6]

//三个参数:遍历项、索引、数组本身
//配合箭头函数,返回大于3的集合

const filterArr2=filterArr.filter((item,index,arr)=>{
    return num>3
})

[4,5]

11、Array.prototype.some

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

const someArr=[false,true,true,false]

//三个参数:遍历项、索引、数组本身
//配合箭头函数,只要有一个是为true,就返回true,一个true都没有,就返回false

const someArr2=someArr.filter((bol,index,arr)=>{
    return bol
})

console.log(someArr2)//true

12、Array.prototype.every

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

const everyArr=[false,true,true,false]

//三个参数:遍历项、索引、数组本身
//配合箭头函数,只要有一个是为true,就返回true,一个true都没有,就返回false

const everyArr2=everyArr.filter((bol,index,arr)=>{
    return bol
})

console.log(everyArr2)//false

13、Array.prototypr.reduce

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

举两个例子:

//计算1+2+3+4+5
const reduceArr=[1,2,3,4,5]
const sum = reduceArr.reduce((pre,next)=>{
    return pre+sum
},0)
console.log(sum)//15


//统计元素出现的个数
    const nameArr = ['hzz', 'wd', 'lhk', 'lhk', 'hzz']
    const totalObj = nameArr.reduce((pre, next) => {
      //由于初始值为{}空对象,因此pre[next]表示obj.next,
      //由于此时{}为空,因此使用pre[]的方式来表示对象的属性
      if (pre[next]) {
        pre[next]++//执行次数加一
      } else {
        pre[next] = 1//表示再次遍历的时候没有重复出现了
      }
      return pre
    }, {})
    console.log(totalObj)//{hzz: 2, wd: 1, lhk: 2}

14、对象属性同名简写

        在之前,同名属性需要这么写

const name = 'Amelian';
const age =22;

const obj={
    name:name,
    age:age
}

cosole.log(obj)//{name:'Amelian',age:22}

对于es6新增的语法,现在只需要这么写

const name = 'Amelian';
const age =22;

//属性同名可简写
const obj={
    name
    age
}

cosole.log(obj)//{name:'Amelian',age:22}

15、Promise

        Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理和更强大。它由社区最早提出把和实现。

        所谓promise,简单来说就是一个容器,里面保存着未来才会结束的事情(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。

        Promise对象有以下特点

  1. 对象的状态不受外界影响,Promise对象代表一个异步操作,有三种状态:pedding(进行中)、fulfilled(已成功)、rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
  2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变只有两种可能:从pending编程fulfilled和从pending编程rejected。只要两种情况发生,状态就凝固了,不会再变了,会一致保持这个结果。这是称为resolved(已定型)

注意:为了行文方便,下面的resolved统一只指fulfilled状态,不包含rejected状态。

有了Promise对象,可以将异步操作以同步操作的操作表达出来,避免层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步更加容易。

15.1 基本用法

ES6规定,Promise对象是一个构造函数,用来生产Promise实例。

下面代码创造了一个Promise实例

    const promise = new Promise(function (resolve, reject) {
      //...some code
      if (/*异步操作成功*/) {
        resolve(value)
      }else{
        reject(error)
      }
    })

Promise构造函数接收一个函数作为参数,该函数的两个参数分别是resolvereject,它们是两个函数,有javaScript引擎提供,不需要自己部署。

        Promise对象编程失败的时候,即异步操作失败的时候调用,并将异步操作报出的错误,作为参数传递出去。

        Promise实例生成,可以用then方法分别制定resolved状态和rejected状态的回调函数。

    promise.then(function (value) {
      //success
    }, function (error) {
      //failure
    })

then方法可以接受两个回调函数作为参数,第一个回调函数式Promise对象的状态编程resolved时调用,第二个回调函数式Promise对象变为rejected时调用,这两个函数都是可选的,不一定要提供,他们都接受Promise对象传出的值作为参数。

下面是一个Promise对象的简单的例子。

    function timeout(ms) {
      return new Promise((resolve, reject) => {
        setTimeout(resolve, ms, 'done')
      })
    }

    timeout(100).then((value) => {
      console.log(value)
    })

上面代码中,timeout方法会返回一个Promise实例,表示一段时间后才会发生结果。过了指定时间(ms参数) 以后,Promise实例的状态变成了resolved,就会触发then方法绑定的回调函数。

Promise新建后就会立即执行

    let promise = new Promise(function (resolve, reject) {
      console.log('Promise');
      resolve();
    })
    promise.then(function () {
      console.log('resolved')
    })
    console.log('hi')

 上面代码中,Promise新建后立即执行,所以首先输出的是Promise

,然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完毕才会执行,所以resolved最后输出。

下面是一个用Promise对象实现的Ajax操作的实例:

const getJSON = function(url) {
  const promise = new Promise(function(resolve, reject){
    const handler = function() {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200) {
        resolve(this.response);
      } else {
        reject(new Error(this.statusText));
      }
    };
    const client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
  console.log('Contents: ' + json);
}, function(error) {
  console.error('出错了', error);
});

 上面代码中,getJSON是对XMLHttpRequest 对象的封装,用于发出一个针对json数据的HTTP请求,并且返回一个Promise对象,需要注意的是,在getJSON内部,resolve和reject函数调用时,都携带了参数。

如果调用resolve函数和reject函数时都带有参数,那么它们的参数会被传递给回调函数(也就是then中的执行的函数)。reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值之外,还可能是例外一个Promise对象,比如下面这样:

    const p1 = new Promise((resolve, reject) => {
      //....
    })
    const p2 = new Promise((resolve, reject) => {
      //....
      resolve(p1)
    })

上面代码中,p1和p2都是promise的实例,但是p2的resolve方法将p1作为参数,即一个异步操作的结果是返回另一个异步操作。也就是说,p1的状态决定了p2的状态,如果p1的状态时pending,那么p2的回调函数就会等待p1的状态改变,如果p1的状态以及是resolved或者reject,那么p2的回调函数将会立即执行。

    const p1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject(new Error('fail'), 3000)
      })
    })
    const p2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(p1, 1000)
      })
    })
    p2.then(result => console.log(result)).catch(error => console.log(error))

注意,这是p1的状态就会传递给p2,

一般来说,调用resolve或reject以后,Promise的使命就完成了,后续的操作应该放在then方法里面。而不应该直接写在resolvereject的后面,所以,最后在他们前面加上return 语句,这样就不会有意外。

new Promise((resolve, reject) => {
  return resolve(1);
  // 后面的语句不会执行
  console.log(2);
})

15.2、Promise.prototype.then()

        Promise实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototypr上的,它的作用是为了Promise实例添加状态改变时的回调函数。前面说过,then方法的第一个参数就是resolved状态的回调函数,第二个参数是rejected状态的回调函数,他们都是可选的。

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例),因此可以使用链式写法,在 then、方法后面再调用另一个then方法。

15.3 、Promise.prototype.catch()

用于指定发生错误时的回调函数。

    getJSON('/posts.json').then(function (posts) {
      //....
    }).catch(function (error) {
      //处理getJSON和前一个回调函数运行时发生的错误
      console.log('发生错误!', error);
    })

上面代码中,getJSON()方法返回一个Promise对象,如果该对象状态为resolved,则会调用then()方法指定的回调函数;如果异步操作 抛出错误,状态就会变成rejected,就会调用catch()方法指定回调函数。处理这个错误,另外,then()方法指定的回调函数如果运行中抛出错误,也会被catch()方法捕获。

        一般来说,不要在then()方法里定义reject状态的回调函数,即then的第二个参数,总是使用catch方法

// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });

上面的代码中,第二种写法要好于第一种写法,理由是第二种写法可以捕获前面then方法执行中的错误,也更接近同步的写法(try/catch),因此,建议总是使用catch()方法,而不使用then()方法的第二个参数。

16、class

以前我们使用够着函数生成对象,这么做

    function Person(name, age) {
      this.name = name;
      this.age = age
    }
    Person.prototype.sayName = function () {
      console.log(this.name)
    }
    const person1 = new Person('hzz', 18)
    console.log(person1)
    person1.sayName()

 tip:class的本质也是functionclassfunction的语法糖

现在有了es6,可以这样做

    class Person {
      constructor(name) {
        this.name = name;
      }
      sayName() {
        console.log(this.name)
      }
    }

    //由于class的本质也是函数,因此通过class创建对象的时候也是通过new的方式
    const person1 = new Person('hzz');
    person1.sayName()//'hzz'

        除了以上,还需要知道class的以上知识点

        静态属性和静态方法,使用static定义的属性和方法只能class自己使用,通过class创造的实例用不了

    class Person {
      constructor(name) {
        this.name = name;
      }
      static age = 22
      static fn() {
        console.log('哈哈')
      }
      sayName() {
        console.log(this.name)
      }
    }

    console.log(Person.age);//22
    Person.fn()//哈哈

    const person1 = new Person('hzz');
    person1.sayName()//'hzz'
    person1.fn()//undefined
    console.log(person1.age)//fn is not a function

extend继承

    class Animal {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
    }

    class Cat extends Animal {
      say() {
        console.log(this.name, this.age);
      }
    }

    const cat1 = new Cat('ketty', 3)// 继承了Animal的构造器
    cat1.say()// ketty 3

17、结构赋值

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

    const obj = {
      name: 'Amelain',
      age: 22,
      gender: '女'
    }

    const name = obj.name;
    const age = obj.age;
    const gender = obj.gender;
    console.log(name, age, gender)//Amelian 22 女

ES6新增了结构赋值的语法

  • 第一个属性是你需要结构赋值对象中的属性名
  • 第二个属性是你想赋值出来的属性的命名,若想与原来的一致,那么就可以省略,反之可以重新定义
  • 嵌套赋值的时候同理,
    const obj = {
      name: 'Amelain',
      age: 22,
      gender: '女',
      doing: {
        morning: '摸鱼',
        afternoon: '摸鱼',
        evening: 'sleep'
      }
    }
    const { name, age, gender } = obj
    console.log(name, age, gender)//Amelian 22 女

    //结构重命名
    const { name: myname } = obj
    console.log(myname)

    //嵌套结构
    const { doing: { evening } } = obj;
    console.log(evening);//sleep

18、find和findIndex

  • find:用于找到第一个符合条件的数组成员,它的参数是一个回调函数,每个数组成员都会执行这个回调函数,找不到返回undefined
  • findIndex:用于找到第一个符合条件的数组成员索引,找不到返回-1
    //这里传递的是一个回调函数,然后findArr数组中的元素都会以此执行这个回调函数
    const arr = [1, 2, 5, 6, 9, 8, 21, 15]
    const res1 = arr.find((value, index, arr) => {
      return value === 9
    })
    console.log(res1)//9 返回被查找的元素
    const res2 = arr.findIndex((value, index, arr) => {
      return value === 9
    })
    console.log(res2)//4 返回所查找元素的索引

19、for in 和 for of

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

先看for in:

    const obj = { name: 'Amelain', age: 22, gender: '女' }
    const arr = [1, 2, 3, 45, 6]
    for (let key in obj) {
      console.log(key + '----->' + obj[key])
    }
    /*
    name----->Amelain
    age----->22
    gender----->女
    */

    for (let index in arr) {
      console.log(index + '----->' + arr[index])
    }

    /*
    0----->1
    1----->2
    2----->3
    3----->45
    4----->6
    */

再看for of:

    for (let item of arr) {
      console.log(item)//逐个输出数组全部元素
    }

总结:for in可以同时对对象和数组进行遍历,遍历得到的直接元素是对象的属性或者数组的索引;for of 遍历数组,得到的直接是数组的元素,不能遍历对象。

20、set和map

20.1 先说说set的用法

    //可不传数组
    const set1 = new Set()
    set1.add(1);
    set1.add(2);
    console.log(set1)//Set(2) {1, 2}

    //也可以传递数组
    const set2 = new Set([1, 2, 3])

    //添加元素使用 add
    set2.add(4);
    set2.add('Amelian')
    console.log(set2)//Set(5) {1, 2, 3, 4, 'Amelian'}

    //检查是否含有某个元素 使用has
    console.log(set2.has(2))//true

    //查看长度
    console.log(set2.size)//5

    //删除元素 使用delete
    set2.delete(2)
    console.log(set2)//Set(4) {1, 3, 4, 'Amelian'}

再说说set的不重复性

    // 增加一个已有的元素,则增加无效,会被自动去重
    const set1 = new Set([1])
    set1.add(1)
    console.log(set1)//Set(1) {1}

    //传入的数组中有重复项,会自动去重
    const set2 = new Set([1, 2, 1, 3, 3, 'Amelian'])
    console.log(set2)//Set(4) {1, 2, 3, 'Amelian'}

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


    //两个对象都是不同指针,所以没法去重
    const set1 = new Set([1, { name: 'Amelian' }, 2, { name: 'Amelian' }])
    console.log(set1)//Set(4) {1, { name: 'Amelian' }, 2, { name: 'Amelian' }}

    //两个对象是同样一个指针,则能去重
    const obj = { name: 'Amelian' }
    const set2 = new Set([1, obj, 2, obj])
    console.log(set2) Set(3) { 1, { name: 'Amelian' }, 2 }

    //我们知道NaN!=NaN,即NaN是自身不等于自身的,但是在Set中还是会被去重掉
    const set = new Set([1, NaN, 1, NaN])
    console.log(set)//Set(2) {1, NaN}

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

    const arr = [1, 2, 14, 7, 8, 9, 2, 1, 7, 9]
    //Set可利用扩展运算符转为数组
    //下面的操作即是先把这个需要去重的数组作为参数传给Set,Set的不重复性会将数组去重
    //去重后已经变为Set对象了,因此需要重新将Set转成数组

    const changeArr = [...new Set(arr)]

    //与上面的操作等价
    const set1 = new Set(arr)
    const quchongArr = [...set1]
    console.log(quchongArr)

20.2 Map

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

    const map1 = new Map()
    //新增键值对 使用set(key,value)
    map1.set(true, 1);
    map1.set(1, 2);
    map1.set('哈哈', 'xixi')
    console.log(map1)//Map(3) {true => 1, 1 => 2, '哈哈' => 'xixi'}

    //判断map中是否含有某个key,使用has(key)
    console.log(map1.has('哈哈'))//true

    //获取map中某个键值对,使用get(key)
    console.log(map1.get(true))//1

    //删除map中某个键值对 使用delete(key)
    map1.delete('哈哈')
    console.log(map1)//Map(2) {true => 1, 1 => 2}


    //定义map,也可以传入键值对数组集合
    const map2 = new Map([[true, 1], [1, 2], ['哈哈', 'xixi']])
    console.log(map2)//Map(3) {true => 1, 1 => 2, '哈哈' => 'xixi'}

 ES7

21、includes

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

    const includeArr = [1, 2, 3, 'Amelian', 'Cifum']
    const isAn = includeArr.includes('Amelian')
    console.log(isAn)//true

22、求幂运算符

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

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

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

const num = 3**2 //9

***************************以下ES8**************************


23、Object.values(obj)

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

    const obj = {
      name: 'Amelian',
      age: 22,
      gender: '女'
    }

    const values = Object.values(obj)
    console.log(values)//['Amelian', 22, '女']

24、Object.entries

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

    const obj = {
      name: 'Amelian',
      age: 22,
      gender: '女'
    }

    const entries = Object.entries(obj)
    console.log(entries)

 25、async/await

 这个是很常用的语法了,我的理解就是:以同步的方式执行异步操作

我们平时可能会遇到这种场景,接口一请求到数据一,而数据一被当做请求二的参数去请求数据二,我们会用promise如下面这样:

    function fn() {
      //模拟第一次请求
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(5)
        }, 1000)
      }).then(res => {
        //模拟第二次请求
        new Promise((resolve, reject) => {
          setTimeout(() => {
            //拿到第一次请求得到数据去*10,当做第二次请求的数据
            resolve(res * 10)
          }, 2000)
        }).then(res => {
          console.log(res)
        })
      })
    }
    fn()//1+2=3  3秒后输出50

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

  • await只能在async函数里使用
  • await后面最好接Promise,如果后面接的是普通函数则会直接执行
  • async函数返回的是一个Promise
    function fn1() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(5)
        }, 1000)
      })
    }

    function fn2(data) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(data * 10)
        }, 2000)
      })
    }

    async function req() {
      //同步的方式执行异步,像排队一样
      const data1 = await fn1()//等待1秒后返回数据再往下继续执行
      const data2 = await fn2(data1)//拿到data1去请求 2秒后,往下走
      console.log(data2) //总共3秒后 输出50
    }
    req()


***************************以下ES9**************************


26、Promise.finally

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

    new Promise((resolve, reject) => {
      resolve('成功喽')
    }).then(
      res => {
        console.log(res),
          err => { console.log(err) }
      }
    ).finally(() => {
      console.log('我是finall')
    })


    new Promise((resolve, reject) => {
      reject('失败哩')
    }).then(
      res => {
        console.log(res),
          err => { console.log(err) }
      }
    ).finally(() => {
      console.log('我是finall')
    })

***************************以下ES9**************************


27、Array.flat

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

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

    //还可以传递参数,参数为降维的次数
    const arr1 = [1, 2, 3, [4, 5, 6, [7, 8, 9]]]
    console.log(arr1.flat(2))//[1, 2, 3, 4, 5, 6, 7, 8, 9]


    //如果传入的参数是一个无限大的数字,那么就表示无论该数组是几维的,均被降维一维数组
    const arr2 = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12]]]]
    console.log(arr2.flat(Infinity))//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

28、Array.flatMap

现有个需求:

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

 将上面的数组转为

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

 第一时间想到 map + flat

    let arr = ["科比 詹姆斯 安东尼", "利拉德 罗斯 麦科勒姆"];
    const arr2 = arr.map((item) => {
      return item.split(" ")//即是将数组中每一项(字符串)每个空格处组成数组

    })
    console.log(arr2)
    //[ ['科比', '詹姆斯', '安东尼'] , ['利拉德', '罗斯', '麦科勒姆'] ]
    console.log(arr2.flat())//['科比', '詹姆斯', '安东尼', '利拉德', '罗斯', '麦科勒姆']

29、?.和?..

29.1   ?.

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

    const list = null;
    //do somethoing
    if (list && list.length) {
      //do something
    }

    //使用可选链
    const list = null;
    if (list?.length) {
      //do something
    }

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

    const obj = {
      cat: {
        name: '哈哈'
      }
    }
    const dog = obj?.dog?.name//undefined

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

    const arr = null;
    const item = arr && arr[1]

    //使用可选链
    const arr = null;
    const item = arr?.[1]

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

    const fn = null;
    //do something
    const res = fn && fn()

    //可选链
    const res = fn?.()

猜你喜欢

转载自blog.csdn.net/weixin_46872121/article/details/122831801