ES6+的一些新语法糖和方法整理
只列举了比较实用的而又鲜为人知的一些,并不绝对全面
ESNext
ES2022
ES2021
ES2020
1. #号创建类的私有变量
class p{
#name='xiaoming'
getName(){
return this.#name
}
}
let a = new p()
console.log(a.getName());
// Property '#name' is not accessible outside class 'p' because it has a private identifier.
console.log(a.#name);// error
class p{
#name='xiaoming'
getName(){
return this.#name
}
}
let a = new p()
console.log(a.getName());
// Property '#name' is not accessible outside class 'p' because it has a private identifier.
console.log(a.#name);// error
2. Promise.allSelected
可以在回调中取到所有的promise的返回值与状态,包括rject的
class p {
#name = 'xiaoming'
getName() {
return this.#name
}
}
let a = new p()
console.log(a.getName());
// console.log(a.#name);
const p1 = new Promise((resolve, reject) => setTimeout(resolve, 1000, 'success'))
const p2 = new Promise((resolve, reject) => setTimeout(reject, 1000, 'fail'))
Promise.allSettled([p1, p2]).then(res => {
console.log(res);
// [
// {status: "fulfilled", value: "success"}
// {status: "rejected", reason: "fail"}
// ]
})
class p {
#name = 'xiaoming'
getName() {
return this.#name
}
}
let a = new p()
console.log(a.getName());
// console.log(a.#name);
const p1 = new Promise((resolve, reject) => setTimeout(resolve, 1000, 'success'))
const p2 = new Promise((resolve, reject) => setTimeout(reject, 1000, 'fail'))
Promise.allSettled([p1, p2]).then(res => {
console.log(res);
// [
// {status: "fulfilled", value: "success"}
// {status: "rejected", reason: "fail"}
// ]
})
3. 空值运算符??
开发中通常会用||去做变量或者值初始化,但是对于空串和0这些有意义值,会有一些意料之外的结果此时就可以用??去替代
?? 运算符只会把 null 和 undefined 判断为 false
const user = {
name: 'xiaoming',
age: '',
height: 0
};
console.log(user.name || 'abc'); // xiaoming
console.log(user.age || 18); // 18
console.log(user.height || 180); // 180
// 使用??
console.log(user.name ?? 'abc'); // xiaoming
console.log(user.age ?? 18); //
console.log(user.height ?? 180); // 0
const user = {
name: 'xiaoming',
age: '',
height: 0
};
console.log(user.name || 'abc'); // xiaoming
console.log(user.age || 18); // 18
console.log(user.height || 180); // 180
// 使用??
console.log(user.name ?? 'abc'); // xiaoming
console.log(user.age ?? 18); //
console.log(user.height ?? 180); // 0
4. 可选链运算符?.
当需要访问嵌套在对象内部好几层的属性时,为了避免出现undefind的报错会使用&&去处理代码
使用可选链可让代码更加简洁明了
let data = {}
// &&
console.log(data && data.a && data.a.b);
// ?.
console.log(data?.a?.b);
let data = {}
// &&
console.log(data && data.a && data.a.b);
// ?.
console.log(data?.a?.b);
5. globalThis
globalThis 目的就是提供一种标准化方式访问全局对象,有了 globalThis 后,你可以在任意上下文,任意时刻都能获取到全局对象
// worker.js
globalThis === self
// node.js
globalThis === global
// browser.js
globalThis === window
// worker.js
globalThis === self
// node.js
globalThis === global
// browser.js
globalThis === window
ES2019/ES10
1. Array.flat
展开数组
let arr = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12]]]];
arr.flat(); // [1, 2, 3, 4, 5, 6, Array(4)];
arr.flat().flat(); // [1, 2, 3, 4, 5, 6, 7, 8, 9, Array(3)];
arr.flat(3); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
// 展开任意层级
arr.flat(Infinity); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
let arr = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12]]]];
arr.flat(); // [1, 2, 3, 4, 5, 6, Array(4)];
arr.flat().flat(); // [1, 2, 3, 4, 5, 6, 7, 8, 9, Array(3)];
arr.flat(3); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
// 展开任意层级
arr.flat(Infinity); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
2. Array.flatMap
与ES6Array.Map()方法相同,但同时也支持展平。该Array.flatMap()方法首先使用映射函数映射每个元素,然后将结果展平为新数组
let arr = [1, 2, 3, 4, 5];
arr.map(x => [x, x * 2]);
// [Array(2), Array(2), Array(2)]
// 0: (2)[1, 2]
// 1: (2)[2, 4]
// 2: (2)[3, 6]
arr.flatMap(v => [v, v * 2]);
// [1, 2, 2, 4, 3, 6, 4, 8, 5, 10]
let arr = [1, 2, 3, 4, 5];
arr.map(x => [x, x * 2]);
// [Array(2), Array(2), Array(2)]
// 0: (2)[1, 2]
// 1: (2)[2, 4]
// 2: (2)[3, 6]
arr.flatMap(v => [v, v * 2]);
// [1, 2, 2, 4, 3, 6, 4, 8, 5, 10]
3. String.trimStart() & String.trimEnd()
String.trimStart()可用于从字符串的开头去掉空白。String.trimEnd()可用于从字符串的尾部去掉空白
let greeting = " Hello everyone";
console.log(greeting.trimStart());
// "Hello everyone"
let greeting = " Hello everyone";
console.log(greeting.trimStart());
// "Hello everyone"
let greeting = "Hello world ";
console.log(greeting.trimEnd());
// "Hello world"
let greeting = "Hello world ";
console.log(greeting.trimEnd());
// "Hello world"
4. 可选 Catch Binding
允许开发人员在catch块中,不使用error参数的情况下使用try/catch
ES2019之前
try {
// some code
}
catch (err) {
// error handling code
}
try {
// some code
}
catch (err) {
// error handling code
}
现在可以
try {
// some code
}
catch {
// error handling code
}
try {
// some code
}
catch {
// error handling code
}
5. Object.fromEntries
Object.fromEntries()创建一个对象或将键值对转换为一个对象。它只接受Iterable
例如:Object.fromEntries(someIterable)
let entries = new Map([["name", "john"], ["age", 22]]);
console.log(Object.fromEntries(entries));
// { name: 'john', age: 22 }
let entries = new Map([["name", "john"], ["age", 22]]);
console.log(Object.fromEntries(entries));
// { name: 'john', age: 22 }
6. Symbol.description
只读描述属性,是一个返回Symbol对象的可选描述的字符串
let mySymbol = `My Symbol`;
let symObj = Symbol(mySymbol);
console.log(symObj) // Symbol(mySymbol);
console.log(String(symObj) === `Symbol(${mySymbol})`); // true
console.log(symObj.description); // "My Symbol"
let mySymbol = `My Symbol`;
let symObj = Symbol(mySymbol);
console.log(symObj) // Symbol(mySymbol);
console.log(String(symObj) === `Symbol(${mySymbol})`); // true
console.log(symObj.description); // "My Symbol"
ES2018/ES9
1. for await of
for of方法能够遍历具有Symbol.iterator接口的同步迭代器数据,但是不能遍历异步迭代器
for await of可以用来遍历具有Symbol.asyncIterator方法的数据结构,也就是异步迭代
for of遍历
function d(timeout: number) {
return new Promise((res, rej) => {
setTimeout(() => {
res(timeout)
}, timeout)
})
}
let data = [d(1000), d(500), d(1200)]
for (const v of data) {
v.then(console.log)
}
// 500
// 1000
// 1200
function d(timeout: number) {
return new Promise((res, rej) => {
setTimeout(() => {
res(timeout)
}, timeout)
})
}
let data = [d(1000), d(500), d(1200)]
for (const v of data) {
v.then(console.log)
}
// 500
// 1000
// 1200
for await of
function d(timeout: number) {
return new Promise((res, rej) => {
setTimeout(() => {
res(timeout)
}, timeout)
})
}
let data = [d(1000), d(500), d(1200)]
async function test() {
for await (const v of data) {
console.log(v);
}
}
test();
// 1000
// 500
// 1200
function d(timeout: number) {
return new Promise((res, rej) => {
setTimeout(() => {
res(timeout)
}, timeout)
})
}
let data = [d(1000), d(500), d(1200)]
async function test() {
for await (const v of data) {
console.log(v);
}
}
test();
// 1000
// 500
// 1200
2. 新的正则表达式特性
2.1 s(dotAll)模式
元字符.
无法匹配换行符,可以通过 s(doAll)flag解决
console.log(/foo.bar/.test('foo\nbar')); // false
// 使用 s
console.log(/foo.bar/s.test('foo\nbar')); // true
console.log(/foo.bar/.test('foo\nbar')); // false
// 使用 s
console.log(/foo.bar/s.test('foo\nbar')); // true
2.2 命名捕获组
在一些正则表达式模式中,使用数字进行匹配可能会令人混淆
命名捕获组,允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用
const re = /(\d{4})-(\d{2})-(\d{2})/;
const match= re.exec('2020-01-01');
console.log(match[0]); // 2020-01-01
console.log(match[1]); // 2020
console.log(match[2]); // 01
console.log(match[3]); // 01
const re = /(\d{4})-(\d{2})-(\d{2})/;
const match= re.exec('2020-01-01');
console.log(match[0]); // 2020-01-01
console.log(match[1]); // 2020
console.log(match[2]); // 01
console.log(match[3]); // 01
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = re.exec('2020-01-01');
console.log(match.groups); // { year: '2020', month: '01', day: '01' }
console.log(match.groups.year); // 2020
console.log(match.groups.month); // 01
console.log(match.groups.day); // 01
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = re.exec('2020-01-01');
console.log(match.groups); // { year: '2020', month: '01', day: '01' }
console.log(match.groups.year); // 2020
console.log(match.groups.month); // 01
console.log(match.groups.day); // 01
使用replace
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
console.log('2020-09-01'.replace(re, '$<month>-$<day>-$<year>')) // 09-01-2020
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
console.log('2020-09-01'.replace(re, '$<month>-$<day>-$<year>')) // 09-01-2020
ES2017/ES8
1. Object.values(),Object.entries()
Object.values方法返回一个数组,其值由对象的值组成
const obj = { a: '1', b: '2' }
console.log(Object.values(obj));
// [ '1', '2' ]
const obj = { a: '1', b: '2' }
console.log(Object.values(obj));
// [ '1', '2' ]
Object.entries()方法返回一个数组,其值为[key,value]
const obj = { a: '1', b: '2' }
console.log(Object.entries(obj));
// [ [ 'a', '1' ], [ 'b', '2' ] ]
const obj = { a: '1', b: '2' }
console.log(Object.entries(obj));
// [ [ 'a', '1' ], [ 'b', '2' ] ]
2. String padding
String.prototype.padStart
在字符串之前补全字符
String.prototype.padEnd
在字符串之后补全
console.log('llo'.padStart(5, 'hello')); // hello
console.log('0'.padEnd(5, '123')); // 01231
console.log('llo'.padStart(5, 'hello')); // hello
console.log('0'.padEnd(5, '123')); // 01231
3 Object.getOwnPropertyDescriptors()
获取指定对象的属性描述符
const obj = { a: 1 };
console.log(Object.getOwnPropertyDescriptor(obj, 'a'));
// { value: 1, writable: true, enumerable: true, configurable: true }
const obj = { a: 1 };
console.log(Object.getOwnPropertyDescriptor(obj, 'a'));
// { value: 1, writable: true, enumerable: true, configurable: true }
ES2016/ES7
1. 求幂运算符**
效果跟Math.pow(x,y)
一致
console.log(2**10); // 1024
console.log(Math.pow(2,10)); // 1024
console.log(2**10); // 1024
console.log(Math.pow(2,10)); // 1024
2. Array.prototype.includes
用法跟String.prototype.includes一致,可读性高于indexOf()
const arr = [1, 2, 'hello']
console.log(arr.includes('hello')); // true
const arr = [1, 2, 'hello']
console.log(arr.includes('hello')); // true