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.
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 ofSet
// 可不传数组 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 toobject
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 isoptional 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 isvacancy coalescing operator
Please see the following code, we use the||
operator, as long as the left side isfalse 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||
??
, onlyundefined 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]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。