ES7-ES12

2022/2/16 JavaScript

# ES7 - Array Includes

Array.indexOf() ES6

const names = ["aaa","bbb","ccc"]

console.log(names.indexOf("aaa")) //0
console.log(names.indexOf("ddd")) //-1
1
2
3
4

Array.includes() ES7新增

const names = ["aaa","bbb","ccc"]


console.log(names.includes("aaa"))//true

//第二个参数,从索引值开始判断
console.log(names.includes("aaa",1))//false

1
2
3
4
5
6
7
8

区别:

indexOf 相比,可以判断 NAN

const names = ["aaa","bbb","ccc", NaN]

console.log(names.indexOf(NaN))
//-1
console.log(names.includes(NaN))
//true

1
2
3
4
5
6
7

# ES7 - 指数运算方法

Math.pow() ES6

const result = Math.pow(3,3) 
console.log(result)//27
1
2

** ES7新增

const result = 3 ** 3 
console.log(result)//27
1
2

# ES8 - Object.values

ES8之前可以通过 Object.keys 获取一个对象所有的 key ,在ES8中提供了 Object.values 来获取所有的 value 值:

const obj = {
    name:"okarin",
    age:18
}

console.log(Object.keys(obj))//[ 'name', 'age' ]
console.log(Object.values(obj))//[ 'okarin', 18 ]
1
2
3
4
5
6
7

注意:

Object.values 的返回值是一个数组,当传入的是一个数组时,会返回数组本身,当传入的是一个字符串时,返回的是一个包含字符串所有的字符的数组

console.log(Object.keys(["abc","cba","nba"]))//[ '0', '1', '2' ]
console.log(Object.values(["abc","cba","nba"]))
//[ 'abc', 'cba', 'nba' ]

console.log(Object.keys("hello"))//[ '0', '1', '2', '3', '4' ]
console.log(Object.values("hello"))//[ 'h', 'e', 'l', 'l', 'o' ]

1
2
3
4
5
6
7

# ES8 - Object.entries

通过 Object.entries 可以获取到一个数组,数组中会存放可枚举属性的键值对数组。

const obj = {
    name:"okarin",
    age:18
}

const arr = Object.entries(obj)
console.log(arr)//[ [ 'name', 'okarin' ], [ 'age', 18 ] ]

const arr = Object.entries(obj)
arr.forEach((item) => {
  console.log(item[0],item[1])
})


1
2
3
4
5
6
7
8
9
10
11
12
13
14

其他:

还可以传入其他类型,如数组。

console.log(Object.entries(["abc","cba","nba"]))
//[ [ '0', 'abc' ], [ '1', 'cba' ], [ '2', 'nba' ] ]
1
2

# ES8 - String Padding

某些字符串我们需要对其进行前后的填充,来实现某种格式化效果,ES8中增加了 padStartpadEnd 方法,分别是对字符串的首尾进行填充的。

const message = "Hello world"
const newMessage = message.padStart(15,"*").padEnd(20,"-")
console.log(newMessage)
1
2
3

# ES8 - Trailing-Commas

ES8允许在函数定义和调用时多加一个逗号

function foo(m,n,){
   console.log(m + n)
}

foo(10,20,)
1
2
3
4
5

# ES8 - Object Descriptors

ES8 Object Descriptors 获取对象的所有属性描述符

详见之前 Object.getOwnPropertyDescriptors() (opens new window)

# ES8 - Async Function

详见之后

# ES9 - Object Spread syntax

ES9之后可以对对象使用展开运算符,详见之前 展开语法(Spread syntax)

# ES9 - Async iterators

后续迭代器详解

ES9 - Async iterators

# ES9 - Promise finally

后面Promise详解

# ES10 -flat flatMap

# flat的使用

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。

const nums  = [10,20,[2,9],[[30,40]],50,[60,90]]
const newNums = nums.flat()
console.log(newNums)//[ 10, 20, 2, 9, [ 30, 40 ], 50, 60, 90 ]

const newNums2 = nums.flat(2)
console.log(newNums2)//[ 10, 20,  2,  9, 30, 40, 50, 60, 90]
1
2
3
4
5
6

# flatMap的使用

flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。

注意一:

  • flatMap 是先进行 map 操作,再做 flat 的操作;

注意二:

  • flatMap 中的 flat 相当于深度为1;
const message = ["hello world","my name is okarin"]

const mapMessage = message.map(res =>{
    return res.split(" ")
})

const flatMessage = message.flatMap(res =>{
    return res.split(" ")
})

console.log(mapMessage)//[ [ 'hello', 'world' ], [ 'my', 'name', 'is', 'okarin' ] ]
console.log(flatMessage)//[ 'hello', 'world', 'my', 'name', 'is', 'okarin' ]

1
2
3
4
5
6
7
8
9
10
11
12
13

# ES10 - Object fromEntries

Object.fromEntries 可以将Entries数组转换为对象

const arr = [ [ 'name', 'okarin' ], [ 'age', 18 ] ]
obj = Object.fromEntries(arr)
console.log(obj)

//obj = { name:"okarin",age:18}

1
2
3
4
5
6

# fromEntries的应用场景

有这样一个数组:[{key:xxx},{value:xxx}]

key value是固定的属性

[
    {key:'alan',value:12},
    {key:'mike',value:18}
]
1
2
3
4

期望值

{alan:12,mike:18}
1

使用 Object.fromEntries

const data = [
    { key: "alan", value: 12 },
    { key: "mike", value: 18 }
];

const result = Object.fromEntries(
    data.map(({ key, value }) => [key, value])
);

console.log(result);
1
2
3
4
5
6
7
8
9
10

# ES10 - Symbol description

详见之前

# ES10 - Optionalcatch binding

见之后

# ES11 - BigInt

在早期的 JavaScript 中,我们不能正确的表示过大的数字:

  • 大于MAX_SAFE_INTEGER的数值,表示的可能是不正确的。

使用BigInt()方法可以将Number转成大数,或者在数值后面加n。

const maxInt = Number.MAX_SAFE_INTEGER

console.log(maxInt + 1)//9007199254740992
console.log(maxInt + 2)//9007199254740992

const bigInt = BigInt(Number.MAX_SAFE_INTEGER)
console.log(bigInt + 1n)//9007199254740992n
console.log(bigInt + 2n)//9007199254740993n
1
2
3
4
5
6
7
8

使用Number(bigInt)可以将大数转成Number类型

# ES11 - Nullish Coalescing 空值合并

使用 ?? 空值合并运算符

const foo = ""

const bar1 = foo || "默认值"
const bar  = foo ?? "默认值"

console.log(bar1)//"默认值"
console.log(bar)//""
1
2
3
4
5
6
7

# ES11 - Optional Chaining 可选链

可选链也是ES11中新增一个特性,主要作用是让我们的代码在进行null和undefined判断时更加清晰和简洁;

const obj = {
    name:"okarin",
    girlFriend:{
        name:"kurisu",
        friend:{
            name:"mayuri"
        }
    }
}

console.log(obj.girlFriend.friend.name)//mayuri
1
2
3
4
5
6
7
8
9
10
11

而比如在另一条世界线中,kurisu不见了。

const obj = {
    name:"okarin",
}

console.log(obj.girlFriend.friend.name)//报错

//等价于
//undefined.friend.name
1
2
3
4
5
6
7
8

此时再执行之前的代码,就会报错。

ES11之前为了防止报错

const obj = {
  name: "okarin",
  girlFriend: {
    name: "kurisu",
    friend: {
      name: "mayuri",
    },
  },
}

if (obj && obj.girlFriend && obj.girlFriend.friend) {
  console.log(obj.girlFriend.friend.name)
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

ES11使用可选链

const obj = {
  name: "okarin",
  girlFriend: {
    name: "kurisu",
    friend: {
      name: "mayuri",
    },
  },
}

console.log(obj.girlFriend?.friend?.name)
1
2
3
4
5
6
7
8
9
10
11

如果取不到值,会直接返回 undefined

# ES11 - Global This

在之前我们希望获取 JavaScript 环境的全局对象,不同的环境获取的方式是不一样的。

  • 比如在浏览器中可以通过 thiswindow 来获取;
  • 比如在Node中我们需要通过globalThis来获取;
console(globalThis)
1

在浏览器环境指向window,在node中指向node的全局对象。

# ES11 - For in 规范

在ES11之前,虽然很多浏览器支持for...in来遍历对象类型,但是并没有被ECMA标准化。

在ES11中,对其进行了标准化,for...in是用于遍历对象的 key 的。

# ES11 - Dynamic Import

见之后

# ES11 - Promise.allSettled

见之后

# ES11 - import meta

见之后

# ES12 - FinalizationRegistry

FinalizationRegistry 对象可以让你在对象被垃圾回收时请求一个回调。

FinalizationRegistry 提供了这样的一种方法:当一个在注册表中注册的对象被回收时,请求在某个时间点上调用一个清理回调。(清理回调有时被称为finalizer);

你可以通过调用register方法,注册任何你想要清理回调的对象,传入该对象和所含的值;

const finalization = new FinalizationRegistry((value)=>{
    console.log(value + "被销毁了")
})

let obj = {name:"okarin"}

finalization.register(obj,"obj")

obj = null

//obj被销毁了
1
2
3
4
5
6
7
8
9
10
11

# ES12 - WeakRef

如果我们默认将一个对象赋值给另外一个引用,那么这个引用是一个强引用:

  • 如果我们希望是一个弱引用的话,可以使用WeakRef;
const finalization = new FinalizationRegistry((value)=>{
    console.log(value + "被销毁了")
})

let obj = {name:"okarin"}
let info = new WeakSet()
info.add(obj)

finalization.register(obj,"obj")

obj = null

//obj被销毁了
1
2
3
4
5
6
7
8
9
10
11
12
13
const finalization = new FinalizationRegistry((value)=>{
    console.log(value + "被销毁了")
})

let obj = {name:"okarin"}
let info = new WeakRef(obj)

finalization.register(obj,"obj")

console.log(info.deref().name)

obj = null

//obj被销毁了
1
2
3
4
5
6
7
8
9
10
11
12
13
14

weakRef.prototype.deref()

如果对象没有销毁,可以获取到原对象

如果已经销毁,那么获取到的是undefined

# ES12 - 逻辑运算符

a ||= b
//等价于
a = a || b

a &&= b
//等价于
a = a && b

a ??= b
//等价于
a = a ?? b
1
2
3
4
5
6
7
8
9
10
11

# ES12 - replaceAll

replaceAll则是返回一个全新的字符串,所有符合匹配规则的字符都将被替换掉,替换规则可以是字符串或者正则表达式。

let string = 'okarin like kurisu,I like u'

//使用replace
let replaceStr = string.replace('like','love')
console.log(replaceStr)  // 'okarin love kurisu,I like u'

//replace使用正则匹配所有
console.log(string.replace(/like/g,'love')) // 'okarin love kurisu,I love u'

//使用replaceAll
let replaceAllStr = string.replaceAll('like','love')
console.log(replaceAllStr) // 'okarin love kurisu,I love u'
1
2
3
4
5
6
7
8
9
10
11
12

需要注意的是,replaceAll在使用正则表达式的时候,如果非全局匹配(/g),则replaceAll()会抛出一个异常

let string = 'okarin like kurisu,I like u'
console.log(string.replaceAll(/like/,'love')) //TypeError
1
2
Last Updated: 2022/3/5上午12:43:44