盘点一下过去 4 年,最让人上瘾的 ES 特性!

2021-03-25 14:29:50 浏览数 (1)

作者:Twan Mulder译者:五柳原文地址:https://medium.com/dailyjs/the-8-best-javascript-features-of-the-last-4-years-40f2ebce4a30


在 1995 年 9 月,网景公司的一位名叫 Brendan Eich 的程序员只用了 10 天就开发出来一个新的脚本语言。

最初,这个脚本语言被命名为 Mocha,但是很快又被称为 LiveScript ,后来才被称为 JavaScript。

自从 JavaScript 被发明以来,JavaScript 成为了世界上使用最多的编程语言之一。

每年,ECMA 都会发布一个带来新特性的 JavaScript 版本。在这篇文章,我将会介绍在过去 4 年里引入的最佳和最实用的特性。

ES2018

展开操作符

ES2015 中最有趣的特性就是展开操作符(Spread Operator)。展开操作符使得复制和合并数组变得更简单。与调用 concat()slice() 不同,你可以使用 ... 操作符:

代码语言:javascript复制
const array1 = [10, 20, 30];
const array2 = [40, 50];
// 合并数组 array2、array1
const merge = [...array1, ...array2];
console.log(merge);
// 输出结果: [10, 20, 30, 40, 50]

ES2018 引入了相同的概念,但针对的是对象:

代码语言:javascript复制
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 }

并且,展开操作符也可以在其他对象中使用,例如:

代码语言:javascript复制
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 的状态是什么。让我们来看一个简单的例子:

代码语言:javascript复制
fetch('file.json')
  .then(data => data.json())
  .catch(error => console.error(error))
  .finally(() => console.log("finished"))
// 输出结果:  "finished"(和 fetch 的结果无关)

ES2019

flat()

flat() 方法可以让你轻松地拍平数组的所有子数组元素。例如,下面这个例子:

代码语言:javascript复制
const arr = ['a', 'b', ['c', 'd']];
const flattened = arr.flat();
console.log(flattened);    
// 输出结果: ["a", "b", "c", "d"]

显然,在这之前你只能使用 reduce()concat() 来获取到拍平后的数组:

代码语言:javascript复制
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.fromEntries() 方法。该方法将对象作为参数,并且以 [key, value] 的方式返回对象本身可枚举(Enumerable)的字符串键值 Key 和属性值 Property。

但是,如果我们想做相反的事情,将键值对列表转为对象呢?

ES2019 引入了新的特性 Object.fromEntries() 方法,通过使用这个方法你就可以做到:

代码语言:javascript复制
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)将使你的代码可读性变得更好!

可选链操作符让你可以每次访问嵌套的对象属性,而不需要验证父属性是否存在。

下面,我们通过例子来比较一下:

代码语言:javascript复制
// 没有使用可选链操作符
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、undefinednullflaseNaN 等等。

在空值合并操作符出现之前,很多时候你可能想检查一个变量是否为空值,它可能会是 undefinednull、空字符串,甚至是一个 false

那么,现在这种情况下,你就可以使用空值合并操作符 ?? 来轻松处理!并且,我想这个时候,可能有同学会说 || 不是有同样的效果吗?下面,我们来通过例子看一下 ||?? 不同的地方:

代码语言:javascript复制
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 部分的第一个字符串:

代码语言:javascript复制
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 的所有字符串,而不需要创建正则表达式:

代码语言:javascript复制
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)主要是一个表面性的改变,对实际代码的性能影响很小,但它可能有助于避免在需要向代码中插入数值时出现错误。

数字分隔符将会加快读取数字的速度,尽管这只是一个非常小的提升。即使,数字分隔符的引入不是一个巨大的更新,并不会改变我们的程序。但是,不可否认的是数字分隔符是一个非常棒的特性:

代码语言:javascript复制
const MILLION = 1_000_000;       // 1000000
const BILLION = 1_000_000_000;   // 1000000000

并且,数字分隔符最酷的地方在于,它还可以用在数字的小数点之后!下面,我们来看一下对应的使用:

代码语言:javascript复制
const BIGNUMBER = 1234_5678_9_0;  // 1234567890
const PI = 3.1415_9265_3589;     // 3.141592653589

另外需要注意的是,以下划线开头或结尾的整数和数字将抛出异常 ReferenceErrorSyntaxError

代码语言:javascript复制
const BAD_PI = 3.14_15_;          // SyntaxError
const NO_MILLION = _1_000_000;    // ReferenceError

点赞?、在看?

通过阅读本篇文章,如果有收获的话,可以点个赞在看,这将会成为我持续分享的动力,感谢~

0 人点赞