过去 4 年,最佳和最实用的 ES 特性!
自从 JavaScript 被发明以来,JavaScript 成为了世界上使用最多的编程语言之一。
每年,ECMA 都会发布一个带来新特性的 JavaScript 版本。在这篇文章,我将会介绍在过去 4 年里引入的最佳和最实用的特性。
ES2018
展开操作符
ES2015 中最有趣的特性就是展开操作符(Spread Operator)。展开操作符使得复制和合并数组变得更简单。与调用 concat()
或 slice()
不同,你可以使用 ...
操作符:
const array1 = [10, 20, 30];
const array2 = [40, 50];
// 合并数组 array2、array1
const merge = [...array1, ...array2];
console.log(merge);
// 输出结果: [10, 20, 30, 40, 50]
ES2018 引入了相同的概念,但针对的是对象:
const object = {
a: 1,
b: 2,
c: 3
};
const { a, ...x } = object;
console.log(a)
console.log(x)
// 输出结果:
// a = 1
// x = { b: 2, c: 3 }
并且,展开操作符也可以在其他对象中使用,例如:
const object1 = { a: 1, b: 2, c: 3 };
const object2 = { ...object1, z: 26 };
console.log(object2)
// 输出结果:
// { a: 1, b: 2, c: 3, z: 26 }
Promise.prototype.finally()
ES2018 的另一个令人激动的特性就是 finally()
方法。
社区中有些 JavaScript 的库(Library)也实现过类似的方法,这在很多场景下非常有用。
使用 finally()
方法,可以执行一段代码,而不必关注 Promise
的状态是什么。让我们来看一个简单的例子:
fetch('file.json')
.then(data => data.json())
.catch(error => console.error(error))
.finally(() => console.log("finished"))
// 输出结果: "finished"(和 fetch 的结果无关)
ES2019
flat()
flat()
方法可以让你轻松地拍平数组的所有子数组元素。例如,下面这个例子:
const arr = ['a', 'b', ['c', 'd']];
const flattened = arr.flat();
console.log(flattened);
// 输出结果: ["a", "b", "c", "d"]
显然,在这之前你只能使用 reduce()
或 concat()
来获取到拍平后的数组:
const arr = ['a', 'b', ['c', 'd']];
const flattened = [].concat.apply([], arr);
// 或者
// const flattened = [].concat(...arr);
console.log(flattened);
// 输出结果: ["a", "b", "c", "d"]
Object.fromEntries()
将数据从一种格式转化成另一种格式,这是我们在使用 JavaScript 的过程中很常见的情景。为了便于将对象 Object
转为数组 Array
,ES2017 引入了 Object.entries()
方法。该方法将对象作为参数,并且以 [key, value]
的方式返回对象本身可枚举(Enumerable)的字符串键值 Key 和属性值 Property。
但是,如果我们想做相反的事情,将键值对列表转为对象呢?
ES2019 引入了新的特性 Object.fromEntries()
方法,通过使用这个方法你就可以做到:
const myArray = [['one', 1], ['two', 2], ['three', 3]];
const obj = Object.fromEntries(myArray);
console.log(obj);
// 输出结果: {one: 1, two: 2, three: 3}
ES2020
可选链操作符
可选链操作符(Optional Chaining)将使你的代码可读性变得更好!
可选链操作符让你可以每次访问嵌套的对象属性,而不需要验证父属性是否存在。
下面,我们通过例子来比较一下:
// 没有使用可选链操作符
let userAdmin = undefined;
if (payload.access && payload.access.admin && payload.access.admin[0]) {
userAdmin = payload.access.admin[0].user;
}
// 使用可选链操作符
const userAdmin = payload.access?.admin?[0]?.user;
可以看到,我们可以不用 let
声明一个变量并包含一些条件来给它赋值,而是直接用 const
声明在一行并不需要任何条件判断。
如果没有找到对象上的属性,将会返回 undefined
。这真的非常实用!
空值合并操作符
空值合并操作符(Nullish Coalescing)增加了可以真正地检查空值(Nullish)的能力,而不是检查它是否为 false
。那么,我想你可能会问空值和 false
的区别是什么?
在 JavaScript 中,许多值转化为 Boolean 类型都会是 false
,像空的字符串、数字 0、undefined
、null
、flase
、NaN
等等。
在空值合并操作符出现之前,很多时候你可能想检查一个变量是否为空值,它可能会是 undefined
、null
、空字符串,甚至是一个 false
。
那么,现在这种情况下,你就可以使用空值合并操作符 ??
来轻松处理!并且,我想这个时候,可能有同学会说 ||
不是有同样的效果吗?下面,我们来通过例子看一下 ||
和 ??
不同的地方:
console.log(0 ?? true) // 0
console.log(0 || true) // true
console.log('' ?? 'Hello World!') // ''
console.log('' || 'Hello World!') // 'Hello World!'
console.log(false ?? true) // false
console.log(false || true) // true
console.log(NaN ?? 5) // Nan
console.log(NaN || 5) // 5
console.log(null ?? true) // true
console.log(null || true) // true
ES2021
String.prototye.replaceAll
String.prototype.replaceAll()
方法可以实现使用另一个字符串的值替换目标字符串中满足 pattern
部分的所有字符串。
在 JavaScript 中,.replace()
方法只会替换目标字符串中满足 pattern
部分的第一个字符串:
let string = "Wow, he doesn't like Porsche? I guess he must be crazy!"
string.replace("he","she")
// 输出结果: "Wow, she doesn't like Porsche? I guess he must be crazy!"
如果我们想替换满足 pattern
部分的所有字符串,实现这个的唯一方式是通过使用正则表达式的全局匹配。虽说使用正则表达式并不是一个坏的方法,但是从性能的角度分析,它并不是最好的。
而使用 .replaceAll()
方法,我们可以一次性更新满足 pattern
的所有字符串,而不需要创建正则表达式:
let string = "Wow, he doesn't like Porsche? I guess he must be crazy!"
string.replaceAll("he","she")
// 输出结果: "Wow, she doesn't like Porsche? I guess she must be crazy!"
数字分割符
现在,数字分隔符(Numeric Separators)主要是一个表面性的改变,对实际代码的性能影响很小,但它可能有助于避免在需要向代码中插入数值时出现错误。
数字分隔符将会加快读取数字的速度,尽管这只是一个非常小的提升。即使,数字分隔符的引入不是一个巨大的更新,并不会改变我们的程序。但是,不可否认的是数字分隔符是一个非常棒的特性:
const MILLION = 1_000_000; // 1000000
const BILLION = 1_000_000_000; // 1000000000
并且,数字分隔符最酷的地方在于,它还可以用在数字的小数点之后!下面,我们来看一下对应的使用:
const BIGNUMBER = 1234_5678_9_0; // 1234567890
const PI = 3.1415_9265_3589; // 3.141592653589
另外需要注意的是,以下划线开头或结尾的整数和数字将抛出异常 ReferenceError
和 SyntaxError
:
const BAD_PI = 3.14_15_; // SyntaxError
const NO_MILLION = _1_000_000; // ReferenceError
点赞👍、在看👀
通过阅读本篇文章,如果有收获的话,可以点个赞和在看,这将会成为我持续分享的动力,感谢~