1. 空值合并 ??
只针对 null 和 undefined,对 ''、 0 、 NaN 及 false 无效,所以这同||是有区别的,写法是 ?? 连接
- obj?.prop // 对象属性
- obj?.[expr] // 同上
- func?.(...args) // 函数或对象方法的调用
// 普通对象
const user = { age 0 }
let age = user.age ?? 50 // value is 0
let ageWrong = user.age || 50 // value is 50
// 函数
funtion register(a, b) {
console.log(a, b);
}
this.register?.(1, 2); // register函数存在,则执行此函数,并且可传参
仅当 age 为 undefined 或者 null 时才使用 50 这个值
2. 可选链 ?.
在对象属前面使用 ?. 连接会检查该属性是否为 null 或 undefined,以避免代码崩溃。
const house = { owner: { name: 'Jim', pet: null }};
// 以前的写法
if(house && house.owner && house.owner.pet && house.owner.pet.type === 'dog'){
console.log('owner has a dog');
}
// 新特性的写法
if (house?.owner?.pet?.type === 'dog') {
console.log('owner has a dog');
}
&&、||运算符一起使用时,需要用括号来表明优先级,要不会报错。
a && b ?? c // 错误
(a && b) ?? c // 正确
3. Promise.allSettled
以前处理多个异步请求一并返回使用的是 Promise.all 但如果其他一个请求失败了就会报出异常,但使用 Promise.allSettled 则不一样,不管请求成功或失败都会把结果返回过来
const promises = [Promise.resolve(1), Promise.reject(2)];
const [result1, result2] = await Promise.allSettled(promises);
即使其他 promise 被拒绝了,我们仍然可以在这里使用 result1 的值。
Promise.all都成功,才会成功,有一个失败,就返回失败。 返回数组,每一个成员都是实例对应的结果。Promise.allSettled一旦结束,状态总是fulfilled,不会变成rejected。 返回数组,数组的每一个成员都是对象,每个对象都有status属性,该属性的值只可能是字符串fulfilled或字符串rejected。fulfilled时,对象有value属性,rejected时有reason属性,对应两种状态的返回值.Promise.race其中一实例返回状态,p的状态就会发生改变,并且不会再变。 只要有返回值,立马停止其他请求。
4. matchAll
如果要用正则表达式查找所有的匹配项,可以用 match 来得到所有子字符串。但是,如果你既需要子字符串又需要索引,该怎么办?这时可以用 matchAll 并进行重复匹配。
const matches = 'Here are some numbers: 3 15 32'.matchAll(/\d+/g);
for (const match of matches) {
console.log(match);
}
// 输出:
// ["3", index: 22, input: "Here are some numbers: 3 15 32", groups: undefined]
// ["15", index: 24, input: "Here are some numbers: 3 15 32", groups: undefined]
// ["32", index: 27, input: "Here are some numbers: 3 15 32", groups: undefined]
ES2020之前
let regex = /t(e)(st(\d?))/g;
let string = 'test1test2test3';
let matches = [];
let match;
while (match = regex.exec(string)) {
matches.push(match);
}
console.log(matches); // 返回正则表达式在当前字符串所有匹配(数组)
可一次性取出所有匹配,但是返回的是一个遍历器(Iterator),而非数组。可以用for of循环取出。
相对于返回数组,返回遍历器的好处在于,如果遍历结果是一个很大的数组,那么遍历器比较节省资源。
遍历器转换成数组,也是比较方便,可以使用...运算符和Array.from()就可以了。
let regex = /t(e)(st(\d?))/g;
let string = 'test1test2test3';
[...string.matchAll(regex)];
// 或
Array.from(string.matchAll(regex));
5. BigInt
在处理大于 9007199254740991 的数字时应该用 BigInt。 BigInt 在数字末尾用 n 表示。
9_007_199_254_740_991 + 2; // 9007199254740992
BigInt(9_007_199_254_740_991) + BigInt(2) // 9007199254740993n
6. 动态导入
以前是先导入再使用,新特性可以动态导入使用了,因为 import() 会与模块一起返回一个 Promise
const utils = await import('utils');
7. globalThis
如果你的代码需要在多个环境(例如浏览器和 Node 服务器)下运行,那么它们所使用全局对象名称并不一致。在浏览器中用的是 window,Node 则用的是 global,而 web worker 用的是 self 。现在,无论代码在哪种环境中运行,globalThis 都能够为你提供正确的全局对象。
if (typeof globalThis.alert === 'function'){
globalThis.alert('hello');
}
8. 管道运算符 |>
有时也会遇到这个场景,一个参数,不断经过函数处理,结果又被当作参数传给下个函数
const result = foo(bar(baz('hello world')))
管道给人的感觉就是一条流水线,从上到下,参数输入,结果输出,很简洁~
const result = 'hello world' |> baz |> bar |>foo
再举个栗子:
const double = (n) => n * 2;
const increment = (n) => n + 1;
double(increment(double(double(5)))); // 42
//使用管道操作符
5 |> double |> double |> increment |> double; // 42
想在项目中使用同样需要babel7,并使用 @babel/plugin-proposal-pipeline-operator 插件
"plugin": [
[
"@babel/plugin-proposal-pipeline-operator",
{
"proposal": "minimal"
}
]
]
注意,在配置 .babelrc 时需要指定 proposal 参数,更多参数请了解
babeljs.io/docs/en/bab…
如果函数还需要别的参数,可以这么写:
const result = 'hello world' |> baz |> (str => baz(str, 'other args')) |> foo
但是如此就看着不简洁了,所以有个备选方案:使用#代表上个结果值,即:
const result = 'hello world' |> baz |> baz(#, 'other args')) |> foo
9. 私有变量
在变量前加 #,可以定义私有变量,仅能在类内部使用
class Message {
#message = "Howdy"
greet() { console.log(this.#message) }
}
const greeting = new Message()
greeting.greet()
console.log(greeting.#message)
如果本文对你有所帮助,感谢点一颗小心心,您的支持是我继续创作的动力!