Skip to content

Commit f01d7a4

Browse files
committed
docs: 新增ES6新特性你知道多少,并部分拆分到其他文章
1 parent d7a52e4 commit f01d7a4

File tree

4 files changed

+581
-124
lines changed

4 files changed

+581
-124
lines changed
Lines changed: 397 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,397 @@
1+
---
2+
title: ES6+新特性你知道多少
3+
tags:
4+
- ECMAScript
5+
---
6+
7+
# ES6+新特性你知道多少
8+
9+
## ES2017
10+
- 允许在函数参数定义、函数调用、字面量对象或数组声明的最后一项加逗号
11+
12+
- SharedArrayBuffer
13+
14+
作用:实现线程间数据共享
15+
16+
API
17+
- byteLength()
18+
- slice()
19+
20+
> 并行指多线程同时执行,并发指单线程轮流执行
21+
>
22+
> JS并行历史:JS 单线程 WebWorker GPU SIMD PJS
23+
24+
- Atomics
25+
26+
作用:保证安全共享数据,线程同步
27+
28+
API
29+
```js
30+
// 线程同步
31+
Atomics.store()
32+
Atomics.load()
33+
Atomics.exchange()
34+
Atomics.compareExchange()
35+
36+
// 原子操作
37+
Atomics.add()
38+
Atomics.and()
39+
Atomics.or()
40+
Atomics.xor()
41+
Atomics.sub()
42+
43+
// 线程通信
44+
Atomics.wait()
45+
Atomics.wake()
46+
Atomics.isLockFree()
47+
```
48+
49+
## ES2018
50+
- [asynchronous iteration via the AsyncIterator protocol and async generators](./ES6上篇#迭代器对象)
51+
52+
- 正则
53+
```javascript
54+
// u表示启用Unicode模式,.可以匹配unicode字符
55+
console.log(new RegExp(/foo.bar/).test('foo\u0000bar')) // true
56+
console.log(new RegExp(/foo.bar/u).test('foo\u0000bar')) // true
57+
58+
59+
// s表示启动dotAll模式,.可以匹配任意字符,包括换行符\n和\r
60+
console.log(new RegExp(/foo.bar/).test('foo\nbar')) // false
61+
console.log(new RegExp(/foo.bar/s).test('foo\nbar')) // true
62+
63+
64+
// Unicode property escapes,匹配特定的Unicode字符集
65+
// \p{Script=XXX}表示匹配XXX,\P{Script=XXX}表示不匹配XXX
66+
// 梵文
67+
console.log(new RegExp(/\p{Script=Devanagari}/u).test('α')) // false
68+
// 希腊字母
69+
console.log(new RegExp(/\p{Script=Greek}/u).test('α')) // true
70+
console.log(new RegExp(/\p{Script_Extensions=Greek}/u).test('α')) // true
71+
// 表情符号
72+
console.log(new RegExp(/\p{Emoji}/u).test('😀')) // true
73+
74+
75+
// 命名捕获组(?<name>正则)
76+
const re1 = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
77+
const result = re1.exec('2018-04-30')
78+
console.log(result) // ["2018-04-30", "2018", "04", "30"]
79+
// \k<name>引用命名捕获组
80+
const re2 = /(?<fruit>apple|banana)===\k<fruit>/
81+
console.log(re2.test('apple===orange')) // false
82+
console.log(re2.test('banana===banana')) // true
83+
// $<name>在replace参数里引用命名捕获组
84+
const re3 = /(?<firstName>[A-Za-z]+)\s(?<lastName>[A-Za-z]+)$/
85+
console.log('Li Qiang'.replace(re3, 'Mr(s) $<lastName> $<firstName>')) // Mr(s) Qiang Li
86+
87+
88+
// 后向断言(look-behind assertions)
89+
// 正则是从右到左的贪婪匹配,也就是说右边匹配最长,左边匹配最短。注意引用捕获组,要放在前,如\1(.),而不是(.)\1,因为是从右到左匹配的
90+
// 匹配后面是B的A:A(?=B)
91+
// 匹配后面不是B的A:A(?!B)
92+
93+
// 相应地,早期已支持前向断言
94+
// 匹配前面是A的B:(?<=A)B
95+
// 匹配前面不是A的B:(?<!A)B
96+
```
97+
98+
- rest parameter and spread operator support for object properties
99+
100+
- [Promise.finally](./ES6系列之Promise基础#finally-callback)
101+
102+
## ES2019
103+
```javascript
104+
// Array.prototype.flat()
105+
// Array.prototype.flatMap()
106+
107+
// Object.fromEntries()
108+
109+
// String.prototype.trimStart()
110+
// String.prototype.trimEnd()
111+
112+
// optional catch binding parameters and allowing U+2028 (LINE SEPARATOR) and U+2029 (PARAGRAPH SEPARATOR) in string literals to align with JSON
113+
114+
// requiring that Array.prototype.sort be a stable sort
115+
116+
// requiring that JSON.stringify return well-formed UTF-8 regardless of input
117+
118+
// clarifying Function.prototype.toString by requiring that it either return the corresponding original source text or a standard placeholder
119+
```
120+
121+
## ES2020
122+
- Promise.allSettled
123+
124+
获取所有Promise结果,无论状态是fulfilled还是rejected
125+
```js
126+
Promise.allSettled([
127+
Promise.reject('error'),
128+
Promise.resolve('success'),
129+
new Promise((resolve,reject)=>{
130+
reject('hello');
131+
}),
132+
new Promise((resolve,reject)=>{
133+
resolve(12138);
134+
})
135+
]).then(res=>{
136+
res.forEach(r=>{
137+
switch(r.status){
138+
case 'fulfilled':
139+
console.log(r.value);
140+
break;
141+
case 'rejected':
142+
console.log(r.reason);
143+
break;
144+
}
145+
})
146+
});
147+
```
148+
149+
- String.prototype.matchAll
150+
151+
一次取出所有匹配。match返回一个元素是匹配字符串的数组,而matchAll返回一个二维数组,元素是包含匹配字符串、匹配字符串在原串中的开始索引index、组group、原串input等信息的一个数组
152+
```js
153+
var matchArr = "[a-[baa-[c".matchAll(/\[[a-z]/g);
154+
for (var val of matchArr) {
155+
console.log(val);
156+
}
157+
```
158+
159+
- 动态导入
160+
161+
`import(module)`可以在任何地方调用,返回一个结果为模块对象的Promise,实现按需加载
162+
163+
`import.meta`表示一个对象,携带模块元信息
164+
165+
```js
166+
window.addEventListener('load', function() {
167+
// 一个模块元信息对象
168+
console.log(import.meta); // {url: "http://127.0.0.1:5500/ES2020/index.html"}
169+
170+
var btnImport = document.querySelector('#btn-import');
171+
btnImport.addEventListener('click', async function() {
172+
var m = await import('./test.js');
173+
console.log(m);
174+
m.func();
175+
})
176+
})
177+
```
178+
179+
- globalThis
180+
181+
一个全新的标准方法用来获取全局this
182+
```js
183+
// window只支持浏览器
184+
// self只支持浏览器和WebWorkers
185+
// global只支持Nodejs
186+
console.log(globalThis === window);
187+
```
188+
189+
- 空位合并操作符??
190+
191+
提高效率,当左侧值为undefined或null时取右侧值,不包括0、false、可转换为false的其他类型
192+
```js
193+
console.log(0 ? 1 : 2); // 2
194+
console.log(0??1); // 0
195+
```
196+
197+
- 可选链操作符?.
198+
199+
简化书写,解决属性多层级调用书写不方便问题
200+
```js
201+
var a = {
202+
b: {
203+
c: 1
204+
}
205+
}
206+
console.log(a?.b?.c); // 1
207+
console.log(a?.b?.c?.d); // undefined
208+
```
209+
210+
- [BigInt数据类型](./ES6上篇.md#bigint数据类型)
211+
212+
- static关键字
213+
```js
214+
class Color {
215+
static red = '#FF0000';
216+
static blue = 'blue';
217+
}
218+
console.log(Color.red);
219+
```
220+
221+
## ES2021
222+
- String.prototype.replaceAll
223+
```javascript
224+
const s = 'hello world'
225+
console.log(s.replaceAll('l', 'L'))
226+
```
227+
228+
- Promise.any
229+
```js
230+
// Promise.any与Promise.race、Promise.all比一比
231+
// Promise.all:若所有Promise成功,则返回所有成功的结果数组,若有一个Promise失败,则返回第一个失败的结果
232+
// Promise.race:返回第一个成功的结果,否则返回第一个失败的结果
233+
// Promise.any: 返回第一个成功的结果,否则抛错
234+
Promise.race([
235+
new Promise((resolve,reject) => {resolve(1)}),
236+
new Promise((resolve,reject) => {resolve(2)}),
237+
new Promise((resolve,reject) => {resolve(3)})
238+
])
239+
.then(res => console.log('then:',res)) // then: 1
240+
.catch(res => console.log('catch:',res))
241+
242+
Promise.all([
243+
new Promise((resolve,reject) => {resolve(1)}),
244+
new Promise((resolve,reject) => {resolve(2)}),
245+
new Promise((resolve,reject) => {resolve(3)})
246+
])
247+
.then(res => console.log(res)) // then: [1,2,3]
248+
.catch(res => console.log('catch:',res))
249+
250+
Promise.any([
251+
new Promise((resolve,reject) => {resolve(1)}),
252+
new Promise((resolve,reject) => {resolve(2)}),
253+
new Promise((resolve,reject) => {resolve(3)})
254+
])
255+
.then(res => console.log('then:',res)) // then: 1
256+
.catch(res => console.log('catch:',res))
257+
258+
259+
Promise.race([
260+
new Promise((resolve,reject) => {reject(1)}),
261+
new Promise((resolve,reject) => {reject(2)}),
262+
new Promise((resolve,reject) => {reject(3)})
263+
])
264+
.then(res => console.log('then:',res))
265+
.catch(res => console.log('catch:',res)) // catch: 1
266+
267+
Promise.all([
268+
new Promise((resolve,reject) => {reject(1)}),
269+
new Promise((resolve,reject) => {reject(2)}),
270+
new Promise((resolve,reject) => {reject(3)})
271+
])
272+
.then(res => console.log('then:',res))
273+
.catch(res => console.log('catch:',res)) // catch: 1
274+
275+
Promise.any([
276+
new Promise((resolve,reject) => {reject(1)}),
277+
new Promise((resolve,reject) => {reject(2)}),
278+
new Promise((resolve,reject) => {reject(3)})
279+
])
280+
.then(res => console.log('then:',res))
281+
.catch(res => console.log('catch:',res)) // catch: AggregateError: All promises were rejected
282+
283+
284+
Promise.race([
285+
new Promise((resolve,reject) => {resolve(1)}),
286+
new Promise((resolve,reject) => {reject(2)}),
287+
new Promise((resolve,reject) => {resolve(3)})
288+
])
289+
.then(res => console.log('then:',res)) // then: 1
290+
.catch(res => console.log('catch:',res))
291+
292+
Promise.all([
293+
new Promise((resolve,reject) => {resolve(1)}),
294+
new Promise((resolve,reject) => {reject(2)}),
295+
new Promise((resolve,reject) => {resolve(3)})
296+
])
297+
.then(res => console.log('then:',res))
298+
.catch(res => console.log('catch:',res)) // catch: 2
299+
300+
Promise.any([
301+
new Promise((resolve,reject) => {resolve(1)}),
302+
new Promise((resolve,reject) => {reject(2)}),
303+
new Promise((resolve,reject) => {resolve(3)})
304+
])
305+
.then(res => console.log('then:',res)) // then: 1
306+
.catch(res => console.log('catch:',res))
307+
```
308+
309+
- AggregateError
310+
311+
- 逻辑运算符:??=、&=、||=
312+
313+
- WeakRef
314+
315+
使JS引擎能及时回收垃圾,无需人工干预。[点这](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/WeakRef)了解更多
316+
```js
317+
let o = {
318+
a:1
319+
}
320+
const weakRefO = new WeakRef(o)
321+
console.log(weakRefO.deref()) // { a: 1 }
322+
// 人工干预,但WeakRef并没有立即回收,说明JS引擎认为它还不是垃圾对象
323+
o = null
324+
console.log(weakRefO.deref()) // { a: 1 }
325+
console.log(o) // null
326+
```
327+
328+
应用:使用弱引用作缓存
329+
```js
330+
const cache = new Map();
331+
const setValue = (key, obj) => {
332+
console.log('cache set...');
333+
cache.set(key, new WeakRef(obj));
334+
};
335+
const getValue = (key) => {
336+
const ref = cache.get(key);
337+
if (ref) {
338+
console.log('cache get...');
339+
return ref.deref();
340+
}
341+
};
342+
343+
function calculateFibonacci(num) {
344+
if(num == 1 || num == 2){
345+
return 1;
346+
}else{
347+
return calculateFibonacci(num - 1) + calculateFibonacci(num - 2);
348+
}
349+
}
350+
console.time('no-cache')
351+
console.log(calculateFibonacci(10));
352+
console.timeEnd('no-cache');
353+
354+
const fibonacciCached = (number) => {
355+
const cached = getValue(number);
356+
if (cached) return cached;
357+
const sum = calculateFibonacci(number);
358+
setValue(number, new Number(sum));
359+
return sum;
360+
};
361+
console.time('cache');
362+
console.log(+fibonacciCached(10));
363+
console.timeEnd('cache');
364+
```
365+
366+
- FinalizationRegistry
367+
368+
- 数字分隔符_
369+
370+
为了提高可读性,启用了下划线作为数字文字中的分隔符
371+
```js
372+
console.log(1_000_000_000_000)
373+
```
374+
375+
- Array新API
376+
```js
377+
// Array.prototype.sort?
378+
379+
// Array.prototype.at支持传负值,倒序获取元素
380+
console.log([12, 34, 56, 78, 90].at(-1)) // 90
381+
382+
// Array.prototype.findLastIndex/Array.prototype.findLast倒序获取符合条件的元素或索引
383+
console.log([12, 34, 56, 78, 90].findLastIndex(val => val < 50)) // 1
384+
console.log([12, 34, 56, 78, 90].findLast(val => val < 50)) // 34
385+
```
386+
387+
## ES2022
388+
<!-- TODO: -->
389+
390+
## ES2023
391+
<!-- TODO: -->
392+
393+
## ES2024
394+
<!-- TODO: -->
395+
396+
## ES2025
397+
<!-- TODO: -->

0 commit comments

Comments
 (0)