ES12(2021)
1、replaceAll
所有符合规则的字符都将被替换掉
const str = 'hello world'
str.replaceAll('l','')//'heo world'
2、Promise.any
Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise
const promise1 = new Promise((resolve, reject) => reject('我是失败的Promise_1'));
const promise2 = new Promise((resolve, reject) => reject('我是失败的Promise_2'));
const promiseList = [promise1, promise2];
Promise.any(promiseList)
.then(values=>{
console.log(values);
})
.catch(e=>{
console.log(e);
});
3、WeakRefs
使用WeakRefs的Class类创建对对象的弱引用(对对象的弱引用是指当该对象应该被GC回收时不会阻止GC的回收行为)
const myWeakRef = new WeakRef({
color: 'red',
lenght: 25
})
myWeakRef.deref()
// => { color: 'red', length: 25 }
myWeakRef.deref().length
// => 25
与 WeakRef 紧密相连的还有另一个功能,名为 finalizers 或 FinalizationRegistry。这个功能允许你注册一个回调函数,这个回调函数将会在对象被垃圾回收时调用。
// 创建 FinalizationRegistry:
const reg = new FinalizationRegistry((val) => {
console.log(val)
})
(() => {
// 创建新对象:
const obj = {}
//为 “obj” 对象注册 finalizer:
//第一个参数:要为其注册 finalizer 的对象。
//第二个参数:上面定义的回调函数的值。
reg.register(obj, 'obj has been garbage-collected.')
})()
// 当 "obj" 被垃圾回收时输出:
// 'obj has be
4、逻辑运算符和赋值表达式
a ||= b
//等价于
a = a || (a = b)
a &&= b
//等价于
a = a && (a = b)
a ??= b
//等价于
a = a ?? (a = b)
5、数字分隔符
数字分隔符,可以在数字之间创建可视化分隔符,通过_下划线来分割数字,使数字更具可读性
const money = 1_000_000_000;
//等价于
const money = 1000000000;
1_000_000_000 === 1000000000; // true
ES11(2020)
那么ES11又引入了那些新特性呢?
\1. String 的 matchAll 方法
\2. 动态导入语句 import()
\3. import.meta
\4. export * as ns from ‘module’
\5. Promise.allSettled
\6. 新增数据类型: BigInt
\7. 顶层对象: globalThis
\8. 空值合并运算符: ??
\9. 可选链操作符:?.
1、matchAll
The matchAll method is a feature that better details regex comparisons within a string.Its result is an array that indicates the positions, as well as the string group and source of the search.See an example of a regex that allows values from 0 to 5 with the matchAll method.
matchAll() 方法返回一个包含所有匹配正则表达式的结果的迭代器。可以使用 for…of 遍历,或者使用 展开运算符(…) 或者 Array.from 转换为数组.
const regex = /[0-5]/g
const year = '2069'
const match = year.matchAll(regex)
for(const item of match){
console.log(item)
}
//['2', index: 0, input: '2069', groups: undefined]
//['0', index: 1, input: '2069', groups: undefined]
console.log(match); // RegExpStringIterator {}
console.log([...match])
可链选操作符号:
可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效
语法:
obj?.prop
obj?.[expr]
arr?.[index]
func?.(args)
用法示例:
let test = (config) => {
//原来我们要获取config里面的db节点的host节点数据的时候,我们可能会写如下的代码进行获取
//const dbHost = config && config.db && config.db.host;
//有了可链选操作符之后,我们可以简化成如下
const dbHost = config?.db?.host;
console.log(dbHost)
}
const config = {
db: {
host: '192.168.0.1',
username: 'root'
},
cache: {
host: '192.168.0.2',
username: 'admin'
}
};
test(config);
2、动态import()
import标准的用法导入的块是静态的,会使所有被带入的模块在加载时就编译,无法做到按需加载编译,降低了首页的加载速度。
在某些场景中,你可能希望根据条件导入模块,或者按需导入模块,这时候就可以使用动态导入代替静态导入。
在import之前,我们需要更具条件导入模块时只能使用require()
if(xxx){
const module = require('./module')
}
//现在这么写
if(xxx){
const module = import('./module')
}
@babel/preset-env 已经包含了 @babel/plugin-syntax-dynamic-import,因此如果要使用 import() 语法,只需要配置 @babel/preset-env 即可。
另外:import() 返回的是一个Promise 对象:
// module.js
export default {
name: 'shenjp'
}
// index.js
if (true) {
let module = import('./module.js');
console.log(module); // Promise {<pending>
module.then(data => console.log(data)); // Module {default: {name: "shenjp"}, __esModule: true, Symbol(Symbol.toStringTag): "Module"}
}
3、import.meta
除了动态引入模块之外,import还提供了一个元属性meta,它包含了当前引入的模块的信息。当前它里面有一个url属性,代表模块被引用的url。想引用可以使用import.meta.url,这个对象可以扩展,并且它的属性都是可写,可配置和可枚举的。
<script type="module" src="my-module.mjs"></script>
因为 import.meta 必须要在模块内部使用,如果不加 type=“module”,控制台会报错:Cannot use ‘import.meta’ outside a module。
在项目中需要下载 @open-wc/webpack-import-meta-loader 才能正常使用。
module: {
rules: [
{
test: /\.js$/,
use: [
require.resolve('@open-wc/webpack-import-meta-loader'),
{
loader: 'babel-loader',
options: {
presets: [
"@babel/preset-env",
"@babel/preset-react"
]
},
}
]
}
]
}
4、exporting modules
新加了一个export的语法跟之前import的语法类似
//Existing in JS
import * as MyCom from './Co.js';
//Added in ES11
export * as MyCom from './Co.js'
5、Promise.allSettled
This attribute allows you to perform a conditional that observes whether all promises in an array have been resolved.
Promise.allSettled方法返回一个在所有给定的promise都fullfilled或者rejected后的promise并返回一个对象数组,每个对象表示对应的promise结果。
使用场景:当你有彼此不依赖的异步任务完成时,或者想知道每个promise的结果时,使用这个方法
相比较之下,promise.all()更适合做互相依赖的promise,只要有一个失败就结束
const myArrayOfPromises = [
Promise.resolve(myPromise),
Promise.reject(0),
Promise.resolve(anotherPromise)
]
Promise.AllSettled(myArrayOfPromises).then ((result) => {
// Do your stuff
console.log(result)
/*
[
{ status: 'fulfilled', value: 100 },
{ status: 'rejected', reason: 'info' },
{ status: 'fulfilled', value: 'name' }
]
*/
})
不同点:
(1)状态
Promise.all
- p1和p2实例状态都为
fulfilled
时,p的状态才会变成fulfilled
,此时p1、p2的返回值组成一个数组,传递给p的回调函数 - 只要p1、p2之中有一个被
rejected
,p的状态就变成rejected
,此时第一个被reject的实例的返回值,会传递给p的回调函数
Promise.allSettled
一旦结束,状态总是fulfilled
,不会变成rejected
(也就是永远进不到p的catch回调)
Promise.race
其中一实例返回状态,p的状态就会发生改变,并且不会再变
(2)返回值
Promise.all
返回数组,每一个成员都是实例对应的结果
Promise.allSettled
返回数组,数组的每一个成员都是对象,每个对象都有status
属性,该属性的值只可能是字符串fulfilled
或字符串rejected
。fulfilled
时,对象有value
属性,rejected
时有reason
属性,对应两种状态的返回值.
Promise.race
每一个实例对应的结果
(3)应用场景
Promise.all
参数Promise实例中是否有被reject的实例,无法确定所有请求都已结束
Promise.allSettled
可以确定所有请求都已结束
Promise.race
只要有返回值,立马停止其他请求
6、BigInt
BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数。在此之前,JS 中安全的最大数字是 9009199254740991,即2^53-1,在控制台中输入 Number.MAX_SAFE_INTEGER 即可查看。超过这个值,JS 没有办法精确表示。另外,大于或等于2的1024次方的数值,JS 无法表示,会返回 Infinity。
BigInt 即解决了这两个问题。BigInt 只用来表示整数,没有位数的限制,任何位数的整数都可以精确表示。为了和 Number 类型进行区分,BigInt 类型的数据必须添加后缀 n.
//Number类型在超过9009199254740991后,计算结果即出现问题
const num1 = 90091992547409910;
console.log(num1 + 1); //90091992547409900
//BigInt 计算结果正确
const num2 = 90091992547409910n;
console.log(num2 + 1n); //90091992547409911n
我们还可以使用 BigInt 对象来初始化 BigInt 实例:
console.log(BigInt(999)); // 999n 注意:没有 new 关键字!!
需要说明的是,BigInt 和 Number 是两种数据类型,不能直接进行四则运算,不过可以进行比较操作。
console.log(99n == 99); //true
console.log(99n === 99); //false
console.log(99n + 1);//TypeError: Cannot mix BigInt and other types, use explicit conversions
7、GlobalThis
对于javascript来说,不同的环境对应的全局对象的获取方式也是不同的,对于浏览器来说通常使用的是window,但是在web worker中使用的是self,而在nodejs中使用的是global。
为了解决在不同环境中的全局对象不同的问题,ES11引入了globalThis,通过这个全局对象,程序员就不用再去区分到底是在哪个环境下了,只需要使用globalThis即可。
var getGlobal = function () {
if (typeof self !== 'undefined') { return self; }
if (typeof window !== 'undefined') { return window; }
if (typeof global !== 'undefined') { return global; }
throw new Error('unable to locate global object');
};
8、空值合并运算符
新增操作符:??。当操作符左侧值为空,返回右侧值,否则返回左侧值。
const someValue = 0;
const defaultValue = 100;
let value = someValue ?? defaultValue;
//0
9、可选链操作符
操作符:?.,允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。
?.操作符的功能类似于.链式操作符,不同的是,在引用为空的时候不会报错。该操作符的短路返回值是undefined
const tortoise = info.animal && info.animal.reptile && info.animal.reptile.tortoise;
因为 null.reptile 或 undefined.reptile 会抛出错误:TypeError: Cannot read property ‘reptile’ of undefined 或 TypeError: Cannot read property ‘reptile’ of null,为了避免报错,如果我们需要访问的属性更深,那么这个这句代码会越来越长。
有了可选链之后我们就可以简化
const tortoise = info.animal?.reptile?.tortoise;
10、空值合并运算符
Nullish coalescing Operator
空值有0,undefined,null,false,NaN
这五个,空值合并操作符是一个逻辑操作符,当左侧操作数为null,undefined时,返回其右侧操作数,否则返回左侧操作数
与逻辑或操作符(||)
不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如,’’ 或 0)时。见下面的例子。
console.log(null ?? "defaultValue1") // "defaultValue1"
console.log(undefined ?? "defaultValue2") // "defaultValue2"
console.log("" ?? "defaultValue3") // ""
console.log(0 ?? "defaultValue4") // 0
console.log(40 ?? "defaultValue5") // 40
||
用于为变量赋默认值,但是如果左侧值为NaN,0,’’,就会导致结果不准确,
let count = 0;
let text = "";
let qty = count || 42;
let message = text || "hi!";
console.log(qty); // 42,而不是 0
console.log(message); // "hi!",而不是 ""
空值合并操作符可以避免这种陷阱,其只在第一个操作数为null
或 undefined
时(而不是其它假值)返回第二个操作数:
let myText = '';
let notFalsyText = myText || 'Hello world';
console.log(notFalsyText); // Hello world
let preservingFalsy = myText ?? 'Hi neighborhood';
console.log(preservingFalsy); // ''
特点:
1、当左表达式不为 null
或 undefined
时,不会对右表达式进行求值。
2、不能直接与AND或OR操作符共用
null || undefined ?? "foo"; // 抛出 SyntaxError
true || undefined ?? "foo"; // 抛出 SyntaxError
//加了括号就没问题
(null || undefined ) ?? "foo"; // 返回 "foo"
Es6-es11
https://segmentfault.com/a/1190000039272641
ES10(2019)
1、Array.flat()和Array.flatMap()
flat
[1,2,[3,4]].flat(Infinity);
// [1,2,3,4]
flatMap
[1,2,3,4].flatMap(a => [a**2])
//[1,4,9,16]
2、String.trimStart()和String.trimEnd()
去除字符串首位空白字符
3、String.prototype.matchAll
为所有匹配的对象返回一个迭代器
const raw_arr = 'test1 test2 test3'.matchAll((/t(e)(st(\d?))/g));
const arr = [...raw_arr];
4、Symbol.prototype.description
只读属性,返回Symbol对象的可选描述的字符串
Symbol('mydescription').description
//'mydescription'
5、Object.fromEntries()
返回一个给定对象自身可枚举属性的健值对数组
const map = new Map(['foo','bar'],['baz',42])
console.log(Object.fromEntries(map))
//{ foo:"bar",baz:42}
6、可选catch
ES9(2018)
1、await和for…of
function getTime(seconds){
return new Promise(resolve=>{
setTimeout(() => {
resolve(seconds)
}, seconds);
})
}
async function test(){
let arr = [getTime(2000),getTime(300),getTime(1000)]
for await (let x of arr){
console.log(x); // 2000 300 1000 按顺序的
}
}
test()
2、promise.finally
Promise.resolve().then(res=> {}).finally()
3、Rest/Spread属性
const values = [1,2,3,4,5,6]
console.log(...values)
//1,2,3,4,5,6
4、正则表达式命名捕获组
允许为每一个组匹配指定一个名字,便于阅读代码,便于引用
const reg = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;
const match = reg.exec('2021-02-23');
console.log(match.groups) // {year: "2021", month: "07", day: "12"}
console.log(match.groups.year) // 2021
console.log(match.groups.month) // 02
console.log(match.groups.day) // 23
5、反向断言
先了解一下正向断言:根据要匹配的字符串后面的字符进行判断和获取
// --正向断言 根据要匹配的字符串的后面的字符进行判断
let str3 = 'hfoahfihaofhfbaidudjlajbaiduadajl88888理财'
const reg3 = /\d+(?=理)/ // 后面的字符是理才满足条件
const result3 = reg3.exec(str3)
console.log(result3)
反向断言就是根据要匹配的字符串前面的字符(字符串)进行判断和获取。
// --- 反向断言 根据要匹配的字符串的前面的字符进行判断
let str4 = 'hfoahfihaofhfb888aidudjlajbaiduadajl88888哈哈'
const reg4 = /(?<=b)\d+/ // b后面的字符是数字才满足条件
const result4 = reg4.exec(str4)
console.log(result4)
//["888",index:14,input:"hfoahfihaofhfb888aidudjlajbaiduadajl88888哈哈"]
6、正则表达式dotAll模式
dotAll(点匹配),都是匹配任意字符,但是很多字符无法匹配,如:
- 四个字节的UTF-16的字符
- 行终止符
\n,\r
换行,回车
console.log(/foo.bar/.test('foo\nbar'))
//false
console.log(/foo.bar/.test('fooabar'))
// true
//加上s可以匹配换行符,加上u可以匹配4位的utf-16字符
console.log(/foo.bar/us.test('foo\nbar'))
ES8(2017)
1、async/await
异步终极解决方案,
2、Object.values()
Object.values({a:1,b:2,c:3})
//[1,2,3]
3、Object.entries()
Object.entries({a:1,b:2,c:3})
//[["a",1],["b",2],["c,3"]]
4、String padding
//padStart
'hello'.padStart(10);//" hello" //五个空格
'hello'.padEnd(10);// "hello "
5、函数参数列表结尾允许逗号
6、Object.getOwnPrototypeDescriptors()
获取一个对象的所有自身属性的描述符,如果没有任何自身属性,则返回空对象
7、ShareArrayBuffer对象
SharedArrayBuffer 对象用来表示一个通用的,固定长度的原始二进制数据缓冲区,
/**
*
* @param {*} length 所创建的数组缓冲区的大小,以字节(byte)为单位。
* @returns {SharedArrayBuffer} 一个大小指定的新 SharedArrayBuffer 对象。其内容被初始化为 0。
*/
new SharedArrayBuffer(10)
8、Atomics对象
Atomics 对象提供了一组静态方法用来对 SharedArrayBuffer 对象进行原子操作。
ES7(2016)
1、Array.prototype.includes()
[2,3,6].includes(6);//true
2、指数操作符
2**10;//2014
ES6(2015)
1、class类
class Man {
constructor(age) {
this.age = name;
}
console() {
console.log(this.age);
}
}
const man = new Man(100);
man.console(); //100
2、模块化ES Module
//模块a
export const sub = (a,b) => a*b
//模块b导入
import {sub} from './A'
3、箭头函数
funct = (a,v) => a*b
4、函数参数默认值
function foo(a = 'fff',b,c) {
}
5、模板字符串
const year = 19
const srt = `You year is ${year}`
6、解构赋值
let a = 12,b=34
let [b,s] = [a,b]//b 12 s 34
7、扩展运算符
8、对象属性简写
const name = '欧豪'
const obj = { name }