关于javascript:基础很好总结了38个ES6ES12的开发技巧倒要看看你能拿几分🐶

前言

大家好,首先表明一下,题目没有歹意哈哈。请原谅本菜鸡。都是为了帮忙大家,大家能够把本人意识几个,得了多少分,发在留言里,一个一分,总分38分。

大家好,我是林三心,这段时间很多兄弟姐妹都来问我问题,我也看过很多他们的代码。给我的感觉就是,代码的应用还停留在了ES5的那个阶段,很多用新语法就能轻松实现的,却都不怎么理解,所以我就打算写一篇文章,总结一下在我工作中用过的十分实用的ES6,ES7,ES8,ES9,ES10,ES11,ES12语法。

首先阐明一下:我这里只是举了最根底的例子,然而我的项目中要怎么去灵活运用,这个就要各位同学本人去摸索了。

ES6

1、let 和 const

这两个的呈现,总感觉是为了开发的代码标准而呈现的。咱们要逐步放弃var,在我的项目中多用let和const

与var的区别:

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

暂时性死区问题阐明:其实let和const是有变量晋升的,然而没有初始化晋升:

var name = '林三心'

function fn () {
  console.log(name)
  let name = 'sunshin_lin'
}
fn() // Cannot access 'name' before initialization

块级作用域解决问题:

for(var i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i)
  })
} // 5 5 5 5 5


for(let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i)
  })
} // 0 1 2 3 4

2、默认参数

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

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

然而这么写的确不优雅,能够应用ES6的默认参数

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

3、扩大运算符

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

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

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

当初的我,能够更优雅地进行拼接

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

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

4、残余参数

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

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

5、模板字符串

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

const name = '林三心'
const age = '22'

console.log(name + '往年' + age + '岁啦') // 林三心往年22岁啦

当初我能够这么做,会更优雅

const name = '林三心'
const age = '22'

console.log(`${name}往年${age}岁啦`) // 林三心往年22岁啦

6、Object.keys

能够用来获取对象的key的汇合,进而能够取得对应key的value

const obj = {
  name: '林三心',
  age: 22,
  gender: '男'
}

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

7、箭头函数

以前咱们应用一般函数

function fn () {}

const fn = function () {}

ES6新加了箭头函数

const fn = () => {}

// 如果只有一个参数,能够省略括号
const fn = name => {}

// 如果函数体里只有一句return
const fn = name => {
    return 2 * name
}
// 可简写为
const fn = name => 2 * name
// 如果返回的是对象
const fn = name => ({ name: name })

一般函数和箭头函数的区别:

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

8、Array.prototype.forEach

ES6新加的数组遍历办法

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) => 2 * num)
console.log(mapArr2)
[ 2, 4, 6, 8, 10 ]

10、Array.prototype.filter

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

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

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

11、Array.prototype.some

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

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

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

12、Array.prototype.every

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

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

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

13、Array.prototype.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 + next
}, 0)
console.log(sum) // 15

// 统计元素呈现个数
const nameArr = ['林三心', 'sunshine_lin', '林三心', '林三心', '科比']
const totalObj = nameArr.reduce((pre, next) => {
  if (pre[next]) {
    pre[next]++
  } else {
    pre[next] = 1
  }
  return pre
}, {})
console.log(totalObj) // { '林三心': 3, sunshine_lin: 1, '科比': 1 }

14、对象属性同名简写

以前同名属性须要这么写

const name = '林三心'
const age = '22'

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

console.log(obj) // { name: '林三心', age: '22' }

ES6新增语法,只需这么写

const name = '林三心'
const age = '22'

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

console.log(obj) // { name: '林三心', age: '22' }

15、Promise

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

看看根本应用

  • 胜利状态

    function requestData () {
    // 模仿申请
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('林三心')
      }, 1000)
    })
    }
    
    requestData().then(res => {
    console.log(res) // 一秒钟后输入 '林三心'
    }, err => {
    console.log(err)
    })
  • 失败状态

    function requestData () {
    // 模仿申请
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        reject('谬误啦')
      }, 1000)
    })
    }
    
    requestData().then(res => {
    console.log(res)
    }, err => {
    console.log(err) // 一秒钟后输入 '谬误啦'
    })
  • all办法

    • 接管一个Promise数组,数组中如有非Promise项,则此项当做胜利
    • 如果所有Promise都胜利,则返回胜利后果数组
    • 如果有一个Promise失败,则返回这个失败后果
    // 如果全都为胜利
    function fn(time) {
    return new Promise((resolve, reject) => {
      console.log(88)
      setTimeout(() => {
        resolve(`${time}毫秒后我胜利啦!!!`)
      }, time)
    })
    }
    
    Promise.all([fn(2000), fn(3000), fn(1000)]).then(res => {
    // 3秒后输入 [ '2000毫秒后我胜利啦!!!', '3000毫秒后我胜利啦!!!', '1000毫秒后我胜利啦!!!' ]
    console.log(res) 
    }, err => {
    console.log(err)
    })
    
    
    
    // 如果有一个失败
    function fn(time, isResolve) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        isResolve ? resolve(`${time}毫秒后我胜利啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
      }, time)
    })
    }
    
    Promise.all([fn(2000, true), fn(3000), fn(1000, true)]).then(res => {
    console.log(res)
    }, err => {
    console.log(err) // 3秒后输入 '3000毫秒后我失败啦!!!'
    })
  • race办法

    • 接管一个Promise数组,数组中如有非Promise项,则此项当做胜利
    • 哪个Promise最快失去后果,就返回那个后果,无论成功失败
    function fn(time, isResolve) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        isResolve ? resolve(`${time}毫秒后我胜利啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
      }, time)
    })
    }
    
    Promise.race([fn(2000, true), fn(3000), fn(1000)]).then(res => {
    console.log(res)
    }, err => {
    console.log(err) // 1秒后输入
    })

16、class

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

function Person(name) {
  this.name = name
}

Person.prototype.sayName = function () {
  console.log(this.name)
}

const kobe = new Person('科比')
kobe.sayName() // 科比

而有了ES6的class能够这么做

class Person {
  constructor(name) {
    // 结构器
    this.name = name
  }

  sayName() {
    console.log(this.name)
  }
}

const kobe = new Person('科比')
kobe.sayName() // 科比

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

class Person {}

console.log(typeof Person) // function

除了以上,还须要晓得class的以下知识点

动态属性和静态方法,应用static定义的属性和办法只能class本人用,实例用不了

class Person {
  constructor(name) {
    this.name = name
  }

  static age = 22

  static fn() {
    console.log('哈哈')
  }
}
console.log(Person.age) // 22
Person.fn() // 哈哈

const sunshine_lin = new Person('林三心')
console.log(sunshine_lin.age) // undefined
sunshine_lin.fn() // 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 cat = new Cat('ketty', 5) // 继承了Animal的结构器
cat.say() // ketty 5

17、解构赋值

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

const obj = {
  name: '林三心',
  age: 22,
  gender: '男'
}

const name = obj.name
const age = obj.age
const gender = obj.gender
console.log(name, age, gender) // 林三心 22 男

ES6新增了解构赋值的语法

const obj = {
  name: '林三心',
  age: 22,
  gender: '男',
  doing: {
    morning: '摸鱼',
    afternoon: '摸鱼',
    evening: 'sleep'
  }
}

const { name, age, gender } = obj
console.log(name, age, gender) // 林三心 22 男

// 解构重名
const { name: myname } = obj
console.log(myname) // 林三心

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

也能够进行数组的解构

const arr = [1, 2, 3]

const [a, b, c] = arr
console.log(a, b, c) // 1 2 3

// 默认赋值
const [a, b, c, d = 5] = arr
console.log(a, b, c, d) // 1 2 3 5

// 乱序解构
const { 1: a, 0: b, 2: c } = arr
console.log(a, b, c) // 2 1 3

18、find 和 findIndex

  • find:找到返回被找元素,找不到返回undefined
  • findIndex:找到返回被找元素索引,找不到返回-1

    const findArr = [
    { name: '科比', no: '24' },
    { name: '罗斯', no: '1' },
    { name: '利拉德', no: '0' }
    ]
    
    const kobe = findArr.find(({ name }) => name === '科比')
    const kobeIndex = findArr.findIndex(({ name }) => name === '科比')
    console.log(kobe) // { name: '科比', no: '24' }
    console.log(kobeIndex) // 0

    19、for of 和 for in

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

    const obj = { name: '林三心', age: 22, gender: '男' }
    const arr = [1, 2, 3, 4, 5]
    
    for(let key in obj) {
    console.log(key)
    }
    name
    age
    gender
    
    for(let index in arr) {
    console.log(index)
  • 1 2 3 4

    再看 for of:

    for(let item of arr) {
    console.log(item)
    }

  • 2 3 4 5

  • Set
    先说说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('林三心')
    console.log(set2) // Set(5) { 1, 2, 3, 4, '林三心' }
    // 是否含有某个元素 应用 has
    console.log(set2.has(2)) // true
    // 查看长度 应用 size
    console.log(set2.size) // 5
    // 删除元素 应用 delete
    set2.delete(2)
    console.log(set2) // Set(4) { 1, 3, 4, '林三心' }

    再说说Set的不重复性

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

    Set的不重复性中,要留神援用数据类型和NaN

    // 两个对象都是不同的指针,所以没法去重
    const set1 = new Set([1, {name: '林三心'}, 2, {name: '林三心'}])
    console.log(set1) // Set(4) { 1, { name: '林三心' }, 2, { name: '林三心' } }
    
    
    // 如果是两个对象是同一指针,则能去重
    const obj = {name: '林三心'}
    const set2 = new Set([1, obj, 2, obj])
    console.log(set2) // Set(3) { 1, { name: '林三心' }, 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, 3, 4, 4, 5, 5, 66, 9, 1]
    
    // Set可利用扩大运算符转为数组哦
    const quchongArr = [...new Set(arr)]
    console.log(quchongArr) // [1,  2, 3, 4, 5, 66, 9]
  • Map
    Map比照object最大的益处就是,key不受类型限度

    // 定义map
    const map1 = new Map()
    // 新增键值对 应用 set(key, value)
    map1.set(true, 1)
    map1.set(1, 2)
    map1.set('哈哈', '嘻嘻嘻')
    console.log(map1) // Map(3) { true => 1, 1 => 2, '哈哈' => '嘻嘻嘻' }
    // 判断map是否含有某个key 应用 has(key)
    console.log(map1.has('哈哈')) // true
    // 获取map中某个key对应的value 应用 get(key)
    console.log(map1.get(true)) // 2
    // 删除map中某个键值对 应用 delete(key)
    map1.delete('哈哈')
    console.log(map1) // Map(2) { true => 1, 1 => 2 }
    
    // 定义map,也可传入键值对数组汇合
    const map2 = new Map([[true, 1], [1, 2], ['哈哈', '嘻嘻嘻']])
    console.log(map2) // Map(3) { true => 1, 1 => 2, '哈哈' => '嘻嘻嘻' }

    ES7

    21、includes

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

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

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

const arr = [1, 2, NaN]

console.log(arr.indexOf(NaN)) // -1  indexOf找不到NaN
console.log(arr.includes(NaN)) // true includes能找到NaN

22、求幂运算符

以前求幂,咱们须要这么写

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

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

const num = 3 ** 2 // 9

ES8

23、Object.values

能够用来获取对象的value的汇合

const obj = {
  name: '林三心',
  age: 22,
  gender: '男'
}

const values = Object.values(obj)
console.log(values) // [ '林三心', 22, '男' ]

24、Object.entries

能够用来获取对象的键值对汇合

const obj = {
  name: '林三心',
  age: 22,
  gender: '男'
}

const entries = Object.entries(obj)
console.log(entries) 
// [ [ 'name', '林三心' ], [ 'age', 22 ], [ 'gender', '男' ] ]

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(sres => {
      console.log(sres)
    })

  })
}
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、for await of

咱们来看以下场景哈

function fn (time) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`${time}毫秒后我胜利啦!!!`)
    }, time)
  })
}

fn(3000).then(res => console.log(res))
fn(1000).then(res => console.log(res))
fn(2000).then(res => console.log(res))

后果是

1000毫秒后我胜利啦!!!
2000毫秒后我胜利啦!!!
3000毫秒后我胜利啦!!!

然而我想要这个后果

3000毫秒后我胜利啦!!!
1000毫秒后我胜利啦!!!
2000毫秒后我胜利啦!!!

第一工夫咱们必定想到的是async/await

function fn (time) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`${time}毫秒后我胜利啦!!!`)
    }, time)
  })
}

async function asyncFn () {
  // 排队
  const data1 = await fn(3000)
  console.log(data1) // 3秒后 3000毫秒后我胜利啦!!!
  const data2 = await fn(1000)
  console.log(data2) // 再过1秒 1000毫秒后我胜利啦!!!
  const data3 = await fn(2000)
  console.log(data3) // 再过2秒 2000毫秒后我胜利啦!!!
}

然而下面代码也是有毛病的,如果有几十个,那不是得写几十个await,有没有一种办法能够通过循环来输入呢?

function fn (time) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`${time}毫秒后我胜利啦!!!`)
    }, time)
  })
}

async function asyncFn () {
  const arr = [fn(3000), fn(1000), fn(1000), fn(2000), fn(500)]
  for await (let x of arr) {
    console.log(x)
  }
}

asyncFn()
3000毫秒后我胜利啦!!!
1000毫秒后我胜利啦!!!
1000毫秒后我胜利啦!!!
2000毫秒后我胜利啦!!!
500毫秒后我胜利啦!!!

27、Promise.finally

新增的Promise办法,无论失败或者胜利状态,都会执行这个函数

// cheng
new Promise((resolve, reject) => {
  resolve('胜利喽')
}).then(
  res => { console.log(res) },
  err => { console.log(err) }
).finally(() => { console.log('我是finally') })

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

ES10

28、Array.flat

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

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

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

还能够传参数,参数为降维的次数

const arr = [1, 2, 3, [4, 5, 6, [7, 8, 9]]]

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

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

const arr = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12]]]]

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

29、Array.flatMap

当初给你一个需要

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

将下面数组转为

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

第一工夫想到map + flat

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

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

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

30、BigInt

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

const theBiggestInt = 9007199254740991n;

const alsoHuge = BigInt(9007199254740991);
// 9007199254740991n

const hugeString = BigInt("9007199254740991");
// 9007199254740991n

const hugeHex = BigInt("0x1fffffffffffff");
// 9007199254740991n

const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111");
// 9007199254740991n

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

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

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

31、Object.fromEntries

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

const arr = [
  ['name', '林三心'],
  ['age', 22],
  ['gender', '男']
]

console.log(Object.fromEntries(arr)) // { name: '林三心', age: 22, gender: '男' }

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

const map = new Map()
map.set('name', '林三心')
map.set('age', 22)
map.set('gender', '男')

console.log(map) // Map(3) { 'name' => '林三心', 'age' => 22, 'gender' => '男' }

const obj = Object.fromEntries(map)
console.log(obj) // { name: '林三心', age: 22, gender: '男' }

32、String.trimStart && String.trimEnd

咱们都晓得JavaScript有个trim办法,能够革除字符串首尾的空格

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

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

const str = '    林三心    '

// 去除首部空格
console.log(str.trimStart()) // '林三心   '
// 去除尾部空格
console.log(str.trimEnd()) // '   林三心'

ES11

33、Promise.allSettled

ES11新增的Promise的办法

  • 接管一个Promise数组,数组中如有非Promise项,则此项当做胜利
  • 把每一个Promise的后果,汇合成数组,返回

    function fn(time, isResolve) {
      return new Promise((resolve, reject) => {
    setTimeout(() => {
      isResolve ? resolve(`${time}毫秒后我胜利啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
    }, time)
      })
    }
    
    Promise.allSettled([fn(2000, true), fn(3000), fn(1000)]).then(res => {
      console.log(res)
      // 3秒后输入 
      [
      { status: 'fulfilled', value: '2000毫秒后我胜利啦!!!' },
      { status: 'rejected', reason: '3000毫秒后我失败啦!!!' },
      { status: 'rejected', reason: '1000毫秒后我失败啦!!!' }
    ]
    })
    

34、?. 和 ??

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

比方咱们须要一个变量,是数组且有长度,才做某些操作

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

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

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

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

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

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

const arr = null
// do something
const item = arr && arr[1]

// 可选链
const arr = null
// do something
const item = arr?.[1]

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

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

// 可选链
const fn = null
// do something
const res = fn?.()
  • 再说说??,中文名为空位合并运算符
    请看以下代码,咱们应用||运算符,只有右边是假值,就会返回左边的数据

    const a = 0 || '林三心' // 林三心
    const b = '' || '林三心' // 林三心
    const c = false || '林三心' // 林三心
    const d = undefined || '林三心' // 林三心
    const e = null || '林三心' // 林三心

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

    const a = 0 ?? '林三心' // 0
    const b = '' ?? '林三心' // ''
    const c = false ?? '林三心' // false
    const d = undefined ?? '林三心' // 林三心
    const e = null ?? '林三心' // 林三心

    ES12

35、Promise.any

E12新增的Promise的办法

  • 接管一个Promise数组,数组中如有非Promise项,则此项当做胜利
  • 如果有一个Promise胜利,则返回这个胜利后果
  • 如果所有Promise都失败,则报错

    // 当有胜利的时候,返回最快那个胜利
    function fn(time, isResolve) {
      return new Promise((resolve, reject) => {
    setTimeout(() => {
      isResolve ? resolve(`${time}毫秒后我胜利啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
    }, time)
      })
    }
    
    Promise.any([fn(2000, true), fn(3000), fn(1000, true)]).then(res => {
      console.log(res) // 1秒后 输入  1000毫秒后我胜利啦
    }, err => {
      console.log(err)
    })
    
    // 当全都失败时
    function fn(time, isResolve) {
      return new Promise((resolve, reject) => {
    setTimeout(() => {
      isResolve ? resolve(`${time}毫秒后我胜利啦!!!`) : reject(`${time}毫秒后我失败啦!!!`)
    }, time)
      })
    }
    
    Promise.any([fn(2000), fn(3000), fn(1000)]).then(res => {
      console.log(res)
    }, err => {
      console.log(err) // 3秒后 报错 all Error
    })

    36、数字分隔符

    数字分隔符能够让你在定义长数字时,更加地高深莫测

    const num = 1000000000
    
    // 应用数字分隔符
    const num = 1_000_000_000

    37、||= 和 &&=

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

不晓得是ES几

38、对象计算属性

咱们常常碰到这样的问题,无论是在微信小程序还是React中,咱们须要依据某个条件去批改某个数据

if (type === 'boy') {
  this.setData({
    boyName: name
  })
} else if (type === 'girl') {
  this.setData({
    girlName: name
  })
}

我也不晓得这个新个性叫啥,我就本人取名叫属性动静属性哈哈哈

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

补充

39、Symbol

利用场景1:应用Symbol来作为对象属性名

平时咱们对象的属性都是字符串

const obj = {
  name: 'Sunshine_Lin',
  age: 23
}
console.log(obj['name']) // 'Sunshine_Lin'
console.log(obj['age']) // 23

其实也能够用Symbol来当做属性名

const gender = Symbol('gender')
const obj = {
  name: 'Sunshine_Lin',
  age: 23,
  [gender]: '男'
}
console.log(obj['name']) // 'Sunshine_Lin'
console.log(obj['age']) // 23
console.log(obj[gender]) // 男

然而Symbol作为属性的属性不会被枚举进去,这也是JSON.stringfy(obj)时,Symbol属性会被排除在外的起因

console.log(Object.keys(obj)) // [ 'name', 'age' ]
for(const key in obj) {
  console.log(key) // name age
}
console.log(JSON.stringify(obj)) // {"name":"Sunshine_Lin","age":23}

其实想获取Symbol属性也不是没方法。

// 办法一
console.log(Object.getOwnPropertySymbols(obj)) // [ Symbol(gender) ]
// 办法二
console.log(Reflect.ownKeys(obj)) // [ 'name', 'age', Symbol(gender) ]

利用场景2:应用Symbol来代替常量

有以下场景

// 赋值
const one = 'oneXin'
const two = 'twoXin'

function fun(key) {
  switch (key) {
    case one:
        return 'one'
      break;
    case two:
        return 'two'
      break;
  }
}

如果变量少的话还好,然而变量多的时候,赋值命名很烦,能够利用Symbol的唯一性

const one = Symbol()
const two = Symbol()

利用场景3:应用Symbol定义类的公有属性

以下例子,PASSWORD属性无奈在实例里获取到

class Login {
  constructor(username, password) {
    const PASSWORD = Symbol()
    this.username = username
    this[PASSWORD] = password
  }
  checkPassword(pwd) { return this[PASSWORD] === pwd }
}

const login = new Login('123456', 'hahah')

console.log(login.PASSWORD) // 报错
console.log(login[PASSWORD]) // 报错
console.log(login[PASSWORD]) // 报错

结语

我是林三心,一个热心的前端菜鸟程序员。如果你上进,喜爱前端,想学习前端,那咱们能够交朋友,一起摸鱼哈哈,摸鱼群,加我请备注【思否】

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理