Object.entries(obj);
2.3 例子
let obj = {a: 1, b: 2};
Object.entries(obj); // [['a', 1], ['b', 2]]
三、Object.values
3.1 返回值
Object.values()
方法返回一个给定对象自身可枚举属性值的数组
3.2 语法
Object.values(obj);
3.3 例子
let obj = {a: 1, b: 2};
Object.values(obj); // [1, 2]
四、Object.getOwnPropertyDescriptors
4.1 返回值
Object.getOwnPropertyDescriptors()
方法用来获取一个对象的所有自身属性的描述符
4.2 语法
Object.getOwnPropertyDescriptors(obj);
4.3 例子
let obj = {a: 1, b: 2};
Object.getOwnPropertyDescriptors(obj); // [a: {configurable: true, enumerable: true, value: 1, writable: true}, b: {configurable: true, enumerable: true, value: 2, writable: true}]
五、Trailing commas
尾后逗号
5.1 定义
如果你想要添加新的属性,并且在上一行已经使用了尾后逗号,你可以仅仅添加新的一行,而不需要修改上一行
5.2 注意
- JSON 不允许尾后逗号
5.3 举例
-
字面量中的尾后逗号
- 对象
let obj = { a: 1, b: 2 }
- 数组
let arr = [ 1, 2 ]
-
函数中的尾后逗号
- 参数定义
function(x, y) {} function(x, y,) {} (x, y) => {} (x, y,) => {}
- 函数调用
fun(x, y) fun(x, y,)
- 不合法的尾后逗号
不含参数或者在剩余参数后面加逗号,都是不合法的尾后逗号
function(,) {} (,) => {} fn(,) function(...arg,) {} (...arg,) => {}
-
解构中的尾后逗号
let [a, b,] = [1, 2];
let {x, y} = {x: 1, y: 2};
- JSON中的尾后逗号
JSON中不允许出现尾后逗号
JSON.parse("[1, 2, 3,]") // ❌
JSON.parse('{"a": 1,}') // ❌
JSON.parse("[1, 2, 3]") // ✅
JSON.parse('{"a": 1}') // ✅
六、String.prototype.padStart()
6.1 定义
padStart()
用另一个字符串填充当前字符串。
6.2 返回值
在原字符串开头填充指定的填充字符串直到目标长度所形成的新字符串。
6.3 语法
str.padStart(targetLength);
str.padStart(targetLength, padString);
- targetLength:当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
- padString(可选):填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的默认值为 " "。
6.4 例子
'abc'.padStart(10); // " abc"
'abc'.padStart(10, "foo"); // "foofoofabc"
'abc'.padStart(6,"123465"); // "123abc"
'abc'.padStart(8, "0"); // "00000abc"
'abc'.padStart(1); // "abc"
七、String.prototype.padEnd()
7.1 定义
padEnd() 方法会用一个字符串填充当前字符串(如果需要的话则重复填充)。
7.2 返回值
返回在原字符串末尾填充指定的填充字符串直到目标长度所形成的新字符串。
7.3 语法
str.padEnd(targetLength)
str.padEnd(targetLength, padString)
- targetLength:当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。
- padString(可选):填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断。此参数的缺省值为 " "。
7.4 例子
'abc'.padEnd(10); // "abc "
'abc'.padEnd(10, "foo"); // "abcfoofoof"
'abc'.padEnd(6, "123456"); // "abc123"
'abc'.padEnd(1); // "abc"
ES9
ES2018(ES9)新增了如下特性👇
Async iterators
异步迭代器Object rest properties
剩余属性Object spread properties
扩展属性Promise.prototype.finally
一、Async iterators
异步迭代器
1.1 返回值
Async iterator
对象的 next() 方法返回一个 Promise
,这个 Promise
的返回值可以被解析成 {value, done}
的格式,
1.2 语法
iterator.next().then(({value, done}) => {});
1.3 举例
const asyncIterator = () => {
const array = [1, 2];
return {
next: function() {
if(array.length) {
return Promise.resolve({
value: array.shift(),
done: false
});
}
return Promise.resolve({
done: true
});
}
}
}
let iterator = asyncIterator();
const test = async() => {
await iterator.next().then(console.log); // {value: 1, done: false}
await iterator.next().then(console.log); // {value: 2, done: false}
await iterator.next().then(console.log); // {done: true}
}
test();
1.4 可以使用 for-await-of
在循环中异步调用函数
const promises = [
new Promise((resolve) => resolve(1)),
new Promise((resolve) => resolve(2)),
new Promise((resolve) => resolve(3)),
];
const test = async() => {
for await (const p of promises) {
console.log('p', p);
}
};
test();
二、Object rest properties
2.1 举例
let test = {
a: 1,
b: 2,
c: 3,
d: 4
}
let {a, b, ...rest} = test;
console.log(a); // 1
console.log(b); // 2
console.log(rest); // {c: 3, d: 4}
2.2 注意
null
不能使用扩展运算符
let {a, b, ...rest} = null; // ❌
三、Object spread properties
3.1 举例
let test = {
a: 1,
b: 2
}
let result = {c: 3, ...test};
console.log(result); // {c: 3, a: 1, b: 2}
let test = null;
let result = {c: 3, ...test}; // {c: 3}
四、Promise.prototype.finally
4.1 定义
在Promise
结束的时候,不管是结果是resolved
还是rejected
,都会调用finally
中的方法
finally
中的回调函数不接受任何参数
4.2 返回值
一个Promise
4.3 语法
const promise = new Promise((resolve, reject) => {
resolve('resolved');
reject('rejectd');
})
promise.then((res) => {
console.log(res);
}).finally(() => {
console.log('finally')
});
4.4 举例
const promise = new Promise((resolve, reject) => {
resolve(1);
reject(2);
});
const test = () => {
console.log(3);
promise.then((res) => {
console.log(4, res);
}).catch(err => {
console.log(5, err);
}).finally(() => {
console.log(6);
});
};
test(); // 3 4 1 6
ES10
ES2019(ES10)新增了如下新特性👇:
Array.prototype.{flat, flatMap}
扁平化嵌套数组Object.fromEntries
String.prototype.{trimStart, trimEnd}
Symbol.prototype.description
Optional catch binding
- Array.prototype.sort() is now required to be stable
一、Array.prototype.{flat, flatMap}
扁平化嵌套数组
1.1 Array.prototype.flat
1.1.1 定义
flat()
方法会按照一个可指定的深度遍历递归数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
1.1.2 语法
arr.flat([depth]);
depth
是数组遍历的深度,默认是1。
1.1.3 返回值
一个新数组,不会改变旧数组。
1.1.4 举例
const arr = [1, 2, [[[[3, 4]]]]];
arr.flat(); // [1, 2, [[[3, 4]]]]
arr.flat(3); // [1, 2, [3, 4]]
arr.flat(-1); // [1, 2, [[[[3, 4]]]]]
arr.flat(Infinity); // [1, 2, 3, 4]
1.1.5 注意
flat()
会移除数组中的空项
let arr = [1, 2, , , 3];
arr.flat(); // [1, 2, 3]
1.1.6 替换
reduce
与contact
let arr = [1, 2, [3, 4]];
arr.reduce((arr, val) => arr.concat(val), []);
...
扩展运算符与contact
let arr = [1, 2, [3, 4]];
[].contact(...arr);
1.2 Array.prototype.flatMap
1.2.1 定义
flatMap()
方法首先使用映射函数映射数组(深度值为1)的每个元素,然后将结果压缩成一个新数组。
1.2.2 返回值
一个新数组,并且每个元素都是回调函数的结果。
1.2.3 语法
arr.flatMap(function callback(currentVal[, index[, array]]) {
}[, thisArg])
- callback: 可以生成一个新数组所调用的函数
- currentVal: 当前数组在处理的元素
- index: 可选,正在处理的元素索引
- array: 可选,被调用的数组
- thisArg: 执行callback函数时使用的this值
1.2.4 举例
let arr = ['My name', 'is', '', 'Lisa'];
let newArr1 = arr.flatMap(cur => cur.split(' '));
let newArr2 = arr.map(cur => cur.split(' '));
console.log(newArr1); // ["My", "name", "is", "", "Lisa"]
console.log(newArr2); // [["My", "name"], ["is"], [""], ["Lisa"]]
二、Object.fromEntries
2.1 定义
fromEntries()
方法会把键值对列表转换成一个对象
2.2 返回值
一个新的对象
2.3 语法
Object.fromEntries(iterable)
- iterable: Array、Map等可迭代对象
2.4 举例
let map = new Map([['a', 1], ['b', 2]]);
let mapToObj = Object.fromEntries(map);
console.log(mapToObj); // {a: 1, b: 2}
let arr = [['a', 1], ['b', 2]];
let arrToObj = Object.fromEntries(arr);
console.log(arrToObj); // {a: 1, b: 2}
let obj = {a: 1, b: 2};
let newObj = Object.fromEntries(
Object.entries(obj).map(
([key, val]) => [key, val * 2]
)
);
console.log(newObj); // {a: 2, b: 4}
三、String.prototype.{trimStart, trimEnd}
3.1 String.prototype.trimStart
3.1.1 定义
trimStart()
方法用来删除字符串的开头的空白字符。
trimLeft()
是它的别名。
3.1.2 返回值
一个新的字符串,这个字符串左边的空格已经被去除掉了。
3.1.3 语法
str.trimStart();
str.trimLeft();
3.1.4 🌰 举例
let str = ' a b cd ';
str.trimStart(); // 'a b cd '
str.trimLeft(); // 'a b cd '
3.2 String.prototype.trimEnd
3.2.1 定义
trimEnd()
方法用来删除字符串末尾的空白字符。 trimRight()
是它的别名
3.2.2 返回值
一个新的字符串,这个字符串右边的空格已经被去除了
3.2.3 语法
str.trimEnd()
str.trimRight()
3.2.4 举例
let str = ' a b cd ';
str.trimEnd(); // ' a b cd'
str.trimRight(); // ' a b cd'
四、Symbol.prototype.description
4.1 定义
description
是一个只读属性
4.2 返回值
它返回Symbol对象的可选描述的字符串
4.3 语法
Symbol('myDescription').description;
Symbol.iterator.description;
Symbol.for('foo').description;
4.4 举例
Symbol('foo').description; // 'foo'
Symbol().description; // undefined
Symbol.for('foo').description; // 'foo'
五、Optional catch binding
可选的捕获绑定,允许省略catch绑定和它后面的圆括号
以前的用法:
try {
} catch(err) {
console.log('err', err);
}
ES10 的用法:
try {
} catch {
}
六、JSON.stringify()
的增强力
JSON.stringify()
在 ES10 修复了对于一些超出范围的 Unicode 展示错误的问题,所以遇到 0xD800-0xDFF 之内的字符会因为无法编码成 UTF-8 进而导致显示错误。在 ES10 它会用转义字符的方式来处理这部分字符而非编码的方式,这样就会正常显示了。
JSON.stringify('😊'); // '"😊"'
七、修订 Function.prototype.toString()
以前的 toString 方法来自 Object.prototype.toString()
,现在 的 Function.prototype.toString()
方法返回一个表示当前函数源代码的字符串。以前只会返回这个函数,不会包含空格、注释等。
function foo() {
// es10新特性
console.log('imooc')
}
console.log(foo.toString());
// function foo() {
// // es10新特性
// console.log('imooc')
// }
ES11
ES2020(ES11)新增了如下新特性👇:
- 空值合并运算符(Nullish coalescing Operator)
- 可选链 Optional chaining
- globalThis
- BigInt
String.prototype.matchAll()
Promise.allSettled()
- Dynamic import(按需 import)
一、空值合并运算符(Nullish coalescing Operator)
1.1 空值合并操作符(??
)
空值合并操作符(??
)是一个逻辑操作符,当左边的操作数为 null
或 undefined
的时候,返回其右侧操作符,否则返回左侧操作符。
undefined ?? 'foo' // 'foo'
null ?? 'foo' // 'foo'
'foo' ?? 'bar' // 'foo'
1.2 逻辑或操作符(||
)
逻辑或操作符(||
),会在左侧操作数为假值时返回右侧操作数,也就是说如果使用 ||
来为某些变量设置默认值,可能会出现意料之外的情况。比如 0、‘’、NaN、false:
0 || 1 // 1
0 ?? 1 // 0
'' || 'bar' // 'bar'
'' ?? 'bar' // ''
NaN || 1 // 1
NaN ?? 1 // NaN
false || 'bar' // 'bar'
false ?? 'bar' // false
1.3 注意
不可以将 ??
与 AND(&&
)OR(||
)一起使用,会报错。
null || undefined ?? "foo"; // 抛出 SyntaxError
true || undefined ?? "foo"; // 抛出 SyntaxError
二、可选链 Optional chaining
2.1 介绍
可选链操作符(?.
)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用都是否有效。?.
操作符的功能类似于.
链式操作符,不同之处在于,在引用为 null
或 undefined
时不会报错,该链路表达式返回值为 undefined
。
以前的写法:
const street = user && user.address && user.address.street;
const num = user && user.address && user.address.getNum && user.address.getNum();
console.log(street, num);
ES11 的写法:
const street2 = user?.address?.street;
const num2 = user?.address?.getNum?.();
console.log(street2, num2);
2.2 注意
可选链不能用于赋值:
let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment
三、globalThis
以前,在 Web 中,可以通过 window
、self
取到全局对象,在 node.js 中,必须使用 global
。
在松散模式下,可以在函数中返回 this
来获取全局对象,但是在严格模式和模块环境下,this
会返回 undefined
。
以前要获取全局对象,可以定义一个函数:
const getGlobal = () => {
if (typeof self !== 'undefined') {
return self
}
if (typeof window !== 'undefined') {
return window
}
if (typeof global !== 'undefined') {
return global
}
throw new Error('无法找到全局对象')
}
const globals = getGlobal()
console.log(globals)
现在 globalThis
提供了一个标准的方式来获取不同环境下的全局对象自身值。
四、BigInt
BigInt 是一种内置对象,用来创建比 2^53 - 1(Number 可创建的最大数字) 更大的整数。可以用来表示任意大的整数
4.1 如何定义一个 BigInt
- 在一个整数字面量后面加 n,例如
10n
- 调用函数
BigInt()
并传递一个整数值或字符串值,例如BigInt(10)
4.2 BigInt 的特点
- BigInt 不能用于 Math 对象中的方法;
- BigInt 不能与任何 Number 实例混合运算,两者必须转换成同一种类型。但是需要注意,BigInt 在转换成 Number 时可能会丢失精度。
- 当使用 BigInt 时,带小数的运算会被向下取整
- BigInt 和 Number 不是严格相等,但是宽松相等
0n === 0 // false
0n == 0 // true
- BigInt 和 Number 可以比较
2n > 2 // false
2n > 1 // true
- BigInt 和 Number 可以混在一个数组中排序
const mixed = [4n, 6, -12n, 10, 4, 0, 0n];
mixed.sort(); // [-12n, 0, 0n, 10, 4n, 4, 6]
- 被 Object 包装的 BigInt 使用 object 的比较规则进行比较,只用同一个对象比较时才相等
0n === Object(0n); // false
Object(0n) === Object(0n); // false
const o = Object(0n);
o === o // true
4.3 BigInt 的方法
4.3.1 BigInt.asIntN()
将 BigInt 值转换为一个 -2^(width-1) 与 2^(width-1) - 1 之间的有符号整数。
4.3.2 BigInt.asUintN()
将一个 BigInt 值转换为 0 与 2^(width) - 1 之间的无符号整数。
4.3.3 BigInt.prototype.toLocaleString()