17
头图

foreword

Hello everyone, first of all, let me make it clear that the title is not malicious haha. Please excuse this chicken. It's all to help everyone, everyone can know how many you know and how many points you get, and send them in the message, each one is one point, and the total score is 38 points.

Hello everyone, my name is Lin Sanxin. During this time, many brothers and sisters have come to ask me questions, and I have also read a lot of their codes. It gives me the feeling that the use of code is still at the stage of ES5. Many can be easily implemented with the new syntax, but I don't know much about it, so I plan to write an article to summarize the use in my work. The very practical ES6,ES7,ES8,ES9,ES10,ES11,ES12 syntax.

First of all, let me explain: I just gave the most basic example here, but how to use it flexibly in the project is up to the students to explore by themselves.

image.png

ES6

1. let and const

The appearance of these two always feels that it appears for the code specification of the development. We have to gradually give up var and use let and const more in the project

Difference with var:

  • var has variable promotion, initialization promotion, variable value
  • let has variable hoisting, no initialization hoisting, value is mutable
  • const has variable promotion, no initialization promotion, the value is immutable, but if it is a definition object, the property is mutable

Temporary dead zone problem description: In fact, let and const have variable promotion, but no initialization promotion:

var name = '林三心'

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

Block scope solves the problem:

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. Default parameters

You have encountered such a problem during development. If the parameters are not passed in, you will set the default parameters

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

But it is really not elegant to write this way, you can use the default parameters of ES6

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

3. Spread operator

Once I wanted to splice multiple arrays, I could only do this

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
]

Now I can stitch more gracefully

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. Remaining parameters

You may have encountered this kind of problem. For a function, the number of incoming parameters is uncertain, so you can use the remaining parameters of 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. Template string

In the past, I could only do this by concatenating strings

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

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

Now I can do this, it will be more elegant

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

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

6、Object.keys

Can be used to obtain the set of keys of the object, and then obtain the value of the corresponding key

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

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

7. Arrow functions

Previously we used normal functions

function fn () {}

const fn = function () {}

ES6 adds arrow functions

const fn = () => {}

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

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

The difference between ordinary functions and arrow functions:

  • 1. Arrow functions cannot be used as constructors, and new cannot be used
  • 2. Arrow functions do not have their own this
  • 3. Arrow functions have no arguments object
  • 4. Arrow functions have no prototype object

8、Array.prototype.forEach

ES6's new array traversal method

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

Often used to return a new array after processing

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

As the name suggests, the method used to 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, which means that as long as one is true, return true

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 is the opposite of some, some is as long as there is one, every is to return true only if all are true

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

  • The first parameter callback function: pre is the value of the last return, next is the item of this traversal of the array
  • The second parameter is the initial value, which is also the first pre

Two examples:

// 计算 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. Shorthand for object properties with the same name

Previously, properties with the same name needed to be written like this

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

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

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

ES6 new syntax, just write like this

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

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

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

15、Promise

Promise , the Chinese name is promise, where is the promise? The promise is that once his state changes, it won't change again. Here is an introduction to the basic use. If you want to understand how to use it in depth, please read my other article will read it, handwritten Promise principle, the most easy-to-understand version! ! !

Check out the basic usage

  • success status

    function requestData () {
    // 模拟请求
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('林三心')
      }, 1000)
    })
    }
    
    requestData().then(res => {
    console.log(res) // 一秒钟后输出 '林三心'
    }, err => {
    console.log(err)
    })
  • failure status

    function requestData () {
    // 模拟请求
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        reject('错误啦')
      }, 1000)
    })
    }
    
    requestData().then(res => {
    console.log(res)
    }, err => {
    console.log(err) // 一秒钟后输出 '错误啦'
    })
  • all method

    • Receive an array of Promise, if there is a non-Promise item in the array, this item is regarded as successful
    • If all Promises succeed, return an array of successful results
    • If a Promise fails, return this failure result
    // 如果全都为成功
    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 method

    • Receive an array of Promise, if there is a non-Promise item in the array, this item is regarded as successful
    • Which Promise gets the result the fastest, returns that result, no matter if it succeeds or fails
    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

Before we used the constructor to generate the object, do this

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

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

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

And with ES6's class you can do this

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

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

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

It is worth mentioning that, class essence is function , class is function of syntactic sugar

class Person {}

console.log(typeof Person) // function

In addition to the above, you also need to know the following knowledge points of class

Static attributes and static methods, static can only be used by the class itself, not by the instance.

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 inheritance

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. Destructuring assignment

Previously want to extract the properties in the object need to do this

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 adds new syntax for destructuring assignment

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

Array destructuring is also possible

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 and findIndex

  • find: find and return the element to be found, if not find return undefined
  • findIndex: find and return the index of the element being found, if not return -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 and for in

  • for in : traversal method, which can traverse objects and arrays
  • for of : traversal method, can only traverse arrays, not non-iterable objects
    First look at 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
    Let's talk about the basic usage of 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, '林三心' }

    Let's talk Set the non-repetitiveness of 061e8c22c9c01d

    // 增加一个已有元素,则增加无效,会被自动去重
    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 the non-repetition of , pay attention to 161e8c22c9c040 reference data type and 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 }

    Using the non-repetitiveness of Set, you can achieve array deduplication

    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 biggest advantage of 061e8c22c9c0ce compared to object is that the key is not restricted by the type of

    // 定义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

    Pass in the element, if the element can be found in the array, return true, otherwise return false

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

Similar to indexOf, but still different

const arr = [1, 2, NaN]

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

22, exponentiation operator

Before exponentiation, we need to write

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

ES7 provides the exponentiation operator: **

const num = 3 ** 2 // 9

ES8

23、Object.values

A collection of values that can be used to get the object

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

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

24、Object.entries

A collection of key-value pairs that can be used to get an object

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

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

25、async/await

This is a very common syntax. My understanding is: performs asynchronous operations synchronously

We may encounter this scenario in ordinary times. Interface 1 requests data 1, and data 1 is used as the parameter of request 2 to request data 2. We will use Promise to do this.

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

Such nesting is not beautiful. If there are many interfaces, there will be many layers of nesting. At this time, we can use async/await to perform asynchronous execution in a synchronous manner. Pay attention to the following points:

  • await can only be used in async functions
  • It is best to connect Promise after await, if it is followed by a normal function, it will be executed directly
  • async function returns a 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

Let's look at the following scenario

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毫秒后我成功啦!!!

but i want this result

3000毫秒后我成功啦!!!
1000毫秒后我成功啦!!!
2000毫秒后我成功啦!!!

The first thing we must think of is 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毫秒后我成功啦!!!
}

But the above code also has shortcomings. If there are dozens of them, it is not necessary to write dozens of awaits. Is there a way to output it through a loop?

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

The newly added Promise method will execute this function regardless of failure or success status

// 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

There is a two-dimensional array, and I want to turn it into a one-dimensional array:

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

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

You can also pass parameters, the parameter is the number of times of dimensionality reduction

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
]

If an infinite number is passed, then the multidimensional array (no matter how many dimensions) is reduced to a one-dimensional array

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

Now give you a request

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

Convert the above array to

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

First thought of map + flat

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

flatMap is flat + map , one method tops two

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

30、BigInt

BigInt is a new JavaScript data type added to ES10. It is used to represent integers 2^53 - 1 2^53 - 1 is the largest number that JavaScript can represent before ES10.

const theBiggestInt = 9007199254740991n;

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

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

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

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

Oh right, since it is a new data type in JavaScript, what is typeof

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

So after the interviewer asks you how many JavaScript data types, do not foolishly planted A6 to A8 species, the ES6 the Symbol and ES10 are BigInt also add to

31、Object.fromEntries

Object.entries of the previous ES8 is to convert the object into an array of key-value pairs, while Object.fromEntries is the opposite, which is to the array of 161e8c22c9c44b key-value pairs into objects

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

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

He also has another use, which is to convert the Map to an object

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

We all know that JavaScript has a trim method that removes spaces at the beginning and end of a string

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

trimStart and trimEnd are used to remove spaces at the beginning and end of the string individually

const str = '    林三心    '

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

ES11

33、Promise.allSettled

ES11's new Promise method

  • Receive an array of Promise, if there is a non-Promise item in the array, this item is regarded as successful
  • Collect the results of each Promise into an array and return

    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. ?. and ??

  • Let's talk about ?. first, the Chinese name is optional chain

For example, we need a variable, which is an array and has a length, to do certain operations

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

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

For example, there is an object, I want to take a value that may not exist, even we are not sure if obj exists

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

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

For example, if there is an array, I am not sure whether it exists or not, if it exists, take the value of index 1

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

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

For example, there is a function, we are not sure if it exists, if it exists, execute it

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

// 可选链
const fn = null
// do something
const res = fn?.()
  • Let's talk about ?? , the Chinese name is vacancy coalescing operator
    Please see the following code, we use the || operator, as long as the left side is false value, it will return the data on the right

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

    The biggest difference between ?? and || ?? , only undefined and null are considered false values

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

    ES12

35、Promise.any

E12's new Promise method

  • Receive an array of Promise, if there is a non-Promise item in the array, this item is regarded as successful
  • If a Promise succeeds, return this success result
  • If all Promises fail, throw an error

    // 当有成功的时候,返回最快那个成功
    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. Number separator

    Number separators make it easier to define long numbers at a glance

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

    37. ||= and &&=

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

I don't know how many ES

38. Object Computed Properties

We often encounter such problems, whether in WeChat applet or React, we need to modify a certain data according to a certain condition

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

I don't know what this new feature is called, so I named it attribute dynamic attribute hahaha

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

Replenish

39、Symbol

Application Scenario 1: Using Symbol as the Object Property Name

Usually the properties of our objects are strings

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

In fact, you can also use Symbol as an attribute name

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]) // 男

However, the attributes of Symbol as attributes will not be enumerated, which is also the reason why Symbol attributes will be excluded when JSON.stringfy(obj)

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}

In fact, it is not impossible to obtain Symbol properties.

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

Scenario 2: Use Symbol instead of constants

There are the following scenarios

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

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

If there are few variables, it is fine, but when there are many variables, assignment and naming are very annoying, and the uniqueness of Symbol can be used.

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

Scenario 3: Use Symbol to define private properties of a class

In the following example, the PASSWORD attribute cannot be obtained in the instance

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]) // 报错

Epilogue

I'm Lin Sanxin, an enthusiastic front-end rookie programmer. If you are motivated, like the front-end, and want to learn the front-end, then we can make friends and fish together haha, touch the fish group, add me, please note [Si No]

image.png


Sunshine_Lin
2.1k 声望7.1k 粉丝