# 详解ECMAScript2019/ES10新属性

Array.prototype.flat()

The flat() method creates a new array with all sub-array elements concatenated into it recursively up to the specified depth. -- MDN

```const nestedArr = [1, 2, [3, 4, [5, 6, [7, [8], 9]]], 10]
console.log(nestedArr.flat())
// [1, 2, 3, 4, [5, 6, [7, [8], 9]], 10]
console.log(nestedArr.flat(2))
// [1, 2, 3, 4, 5, 6, [7, [8], 9], 10]
console.log(nestedArr.flat(3))
// [1, 2, 3, 4, 5, 6, 7, [8], 9, 10]
console.log(nestedArr.flat(4))
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(nestedArr.flat(Infinity))
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

Array.prototype.flatMap()

The flatMap() method first maps each element using a mapping function, then flattens the result into a new array. It is identical to a map() followed by a flat() of depth 1, but flatMap() is often quite useful, as merging both into one method is slightly more efficient. -- MDN

```const myArr = [1, 2, 3]
myArr
.map(n => [n * n]) // [[1], [4], [9]]
.flat() // [1, 4, 9]

// 用flatMap可以一步到位
myArr.flatMap(n => [n * n]) // [1, 4, 9]

```

```// 假如我们想要删除掉原数组里面所有的负数，同时将单数转换为一个复数和1
const a = [5, 4, -3, 20, 17, -33, -4, 18]
//    |  x  |  |   x  x  |
//    [4,1, 4,  20, 16,1,     18]
a.flatMap(n =>
(n < 0) ? []: // 删除负数
(n % 2 == 0) ? [n] : // 保留复数
[n - 1, 1] // 单数变为一个复数和1
)
// [4, 1, 4, 20, 20, 16, 1, 18]
```

Object.fromEntries()

The Object.fromEntries() method transforms a list of key-value pairs into an object. --MDN

fromEntries方法将一个iterable对象返回的一系列键值对(key-value pairs)转换为一个object。先看一个简单的例子理解一下:

```// key-value pairs数组
const entriesArr = [["k1", 1], ["k2", 2]]
console.log(Object.fromEntries(entriesArr)
// {k1: 1, k2: 2}

const entriesMap = new Map([
["k1", 1],
["k2", 2]
]) // {"k1" => 1, "k2" => 2}
console.log(Object.fromEntries(entriesMap))
// {k1: 1, k2: 2}

```

```const iteratorObj = {
[Symbol.iterator]: function () {
const entries = [["k1", 1], ["k2", 2]]
let cursor = 0

return {
next() {
const done = entries.length === cursor

return {
value: done ? undefined : entries[cursor++],
done
}
}
}
}
}
Object.fromEntries(iteratorObj) // {k1: 1, k2: 2}

```

```const studentMap = {
}
const goodStudentMap = Object.fromEntries(
Object
.entries(studentMap)
.filter(([_, meta]) => meta.grade >= 60)
)
console.log(goodStudentMap)
```

String.prototype.trimStart

```const greeting = "  Hello world! "
console.log(greeting.trimStart())
// "Hello world! "
```

String.prototype.trimEnd

```const greeting = " Hello world! "
console.log(greeting.trimEnd())
// " Hello world!"
```

Symbol.prototype.description

The read-only description property is a string returning the optional description of Symbol objects. -- MDN

ECMAScript2019给Symbol对象添加了一个可选的description属性，这个属性是个只读属性，看看例子:

```console.log(Symbol("desc").description)
// desc
console.log(Symbol.for("desc").description)
// desc

// 一些内置的Symbol也有这个属性
console.log(Symbol.iterator.description)
// Symbol.iterator

// 如果初始化时没有带description，这个属性会返回一个undefined，因为这样才说这个属性是可选的
console.log(Symbol().description)
// undefined

// 这个属性是只读的，不能被设置
Symbol.iterator.description = "mess it"
console.log(Symbol.iterator.description)
// Symbol.iterator

```

```var s1 = Symbol("desc")
var s2 = Symbol("desc")
console.log(s1.description === s2.description)
// true
console.log(s1 === s2)
// false```

try catch optional binding

ECMAScript2019之后，你写try...catch时如果没必要时可以不用声明error：

```// ECMAScript2019之前，你一定要在catch里面声明error，否则会报错
try {
...
} catch (error) {

}
// 可是有时候，你确实用不到这个error对象，于是你会写这样的代码
try {
...
} catch (_) {
...
}

// ECMAScript2019后，你可以直接这样写了
try {
...
} catch {
...
}

```

```let testJSONObj
try {
testJSONObj = JSON.prase(testStr)
} catch {
testJSONObj = {}
}
console.log(testJSONObj)
```

ECMAScript2019后Array.sort一定是个稳定的排序。什么是稳定排序？所谓的稳定排序就是：假如没排序之前有两个相同数值的元素a[i]和a[j]，而且i在j前面，即i < j，经过排序后元素a[i]依然排在a[j]元素的前面，也就是说稳定的排序不会改变原来数组里面相同数值的元素的先后关系。看个例子：

```var users = [
{name: "Sean", rating: 14},
{name: "Ken", rating: 14},
{name: "Jeremy", rating: 13}
]
users.sort((a, b) => a.rating - b.rating)
// 非稳定的排序结果可能是
// [
//  {name: "Jeremy", rating: 13},
//  {name: "Ken", rating: 14},
//  {name: "Sean", rating: 14}
// ]
// 虽然Sean和Ken具有同样的rating，可是非稳定的排序不能保证他们两个的顺序在排序后保持不变

// ECMAScript2019后，Array.sort将是一个稳定的排序，也就是说它可以保证Sean和Ken两个人的顺序在排序后不变
// [
//  {name: "Jeremy", rating: 13},
//  {name: "Sean", rating: 14},
//  {name: "Ken", rating: 14}
// ]

```

ECMAScript2019之前，调用function的toString方法会将方法体里面的空格字符省略掉，例如:

```function hello() {
console.log("hello word")
}

console.log(hello.toString())
//"function hello() {
console.log("hello word")
}"

```

ECMAScript2019之后，要求一定要返回函数源代码（保留空格字符）或者一个标准的占位符例如native code，所以ECMAScript2019之后，以上的输出会变为：

```console.log(hello.toString())
//"function hello() {
// console.log("hello word")
//}"
```