DailyENJS 致力于翻译优秀的前端英文技术文章,为技术同学带来更好的技术视野。

ECMAScript 2015,也称为ES6,是一个花了六年时间才完成的主要版本。从那时起,负责制定ECMAScript标准的 TC39 每年都会发布新版本的标准。这个年度发布周期简化了流程,并快速提供了新特性,这也收到了 JavaScript 社区的欢迎。
今年,ECMAScript 2019(简称ES2019)将会发布。新功能包括 Object.fromEntries(),trimStart(),trimEnd(),flat(),flatMap(),symbol 的 description 属性,可选的catch参数等。
好消息是这些功能已经在最新版本的Firefox和Chrome中实现,并且它们也可以被转换,以便旧版浏览器能够处理它们。在这篇文章中,我们将仔细研究这些功能,看看他们如何 upgrade the language。
1. Object.fromEntries()
在JavaScript中,将数据从一种格式转换为另一种格式非常常见。为了便于将对象转换为数组,ES2017引入了 Object.entries() 方法。此方法将对象作为参数,并以 [key,value] 的形式返回对象自己的可枚举的键值对的数组。例如:
const obj = {one: 1, two: 2, three: 3};
console.log(Object.entries(obj));
// => [["one", 1], ["two", 2], ["three", 3]]
但是如果我们想要做相反的事情将键值对列表转换为对象呢?某些编程语言(如Python)为此提供了dict() 函数。在 Underscore.js 和 Lodash 中还有 _.fromPairs 函数。
const myArray = [['one', 1], ['two', 2], ['three', 3]];
const obj = Object.fromEntries(myArray);
console.log(obj); // => {one: 1, two: 2, three: 3}
如您所见,Object.fromEntries() 只是 Object.entries() 的逆操作。虽然以前可以实现相同的结果,但它并不是非常简单:
const myArray = [['one', 1], ['two', 2], ['three', 3]];
const obj = Array.from(myArray).reduce((acc, [key, val]) => Object.assign(acc, {[key]: val}), {});
console.log(obj); // => {one: 1, two: 2, three: 3}
请记住,传递给 Object.fromEntries() 的参数可以是可迭代的任何对象。
例如,在以下代码中·Object.fromEntries() 将 Map 对象作为参数,并创建一个新对象,其键和对应值由Map给出:
const map = new Map();
map.set('one', 1);
map.set('two', 2);
const obj = Object.fromEntries(map);
console.log(obj); // => {one: 1, two: 2}
Object.fromEntries() 方法对于转换对象也非常有用。请考虑以下代码:
const obj = {a: 4, b: 9, c: 16};
// convert the object into an array
const arr = Object.entries(obj);
// get the square root of the numbers
const map = arr.map(([key, val]) => [key, Math.sqrt(val)]);
// convert the array back to an object
const obj2 = Object.fromEntries(map);
console.log(obj2); // => {a: 2, b: 3, c: 4}
此代码将对象中的值转换为其平方根。为此,它首先将对象转换为数组,然后使用 map()方法获取数组中值的平方根。结果是可以转换回对象的数组数组。
Object.fromEntries() 派上用场的另一种情况是使用URL的查询字符串时,如下例所示:
const paramsString = 'param1=foo¶m2=baz';
const searchParams = new URLSearchParams(paramsString);
Object.fromEntries(searchParams);
在此代码中,查询字符串将传递给 URLSearchParams() 构造函数。然后将返回值(即URLSearchParams对象实例)传递给 Object.fromEntries() 方法。结果是一个包含每个参数作为属性的对象。
Object.fromEntries() 方法目前是第4阶段提案,这意味着它已准备好包含在ES2019标准中。
2. trimStart() 和 trimEnd()
trimStart() 和 trimEnd() 方法在功能上与 trimLeft() 和 trimRight() 相同。这些方法目前是第4阶段提案,并将添加到规范中以与 padStart() 和 padEnd() 保持一致。我们来看一些例子:
const str = " string ";
// es2019
console.log(str.trimStart()); // => "string "
console.log(str.trimEnd()); // => " string"
// the same as
console.log(str.trimLeft()); // => "string "
console.log(str.trimRight()); // => " string"
对于Web兼容性,trimLeft() 和 trimRight() 将保留为 trimStart() 和 trimEnd() 的别名。
3. flat() 和 flatMap()
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);
// or
// const flattened = [].concat(...arr);
console.log(flattened); // => ["a", "b", "c", "d"]
请注意,如果提供的数组中有任何空元素,它们将被丢弃:
const arr = ['a', , , 'b', ['c', 'd']];
const flattened = arr.flat();
console.log(flattened); // => ["a", "b", "c", "d"]
flat() 还接受一个可选参数,该参数指定嵌套数组应该被展平的级别数。
如果未提供参数,则将使用默认值1:
const arr = [10, [20, [30]]];
console.log(arr.flat()); // => [10, 20, [30]]
console.log(arr.flat(1)); // => [10, 20, [30]]
console.log(arr.flat(2)); // => [10, 20, 30]
flatMap() 方法将 map() 和 flat() 组合成一个方法。它首先使用提供的函数的返回值创建一个新数组,然后连接该数组的所有子数组元素。一个例子应该使这更清楚:
const arr = [4.25, 19.99, 25.5];
console.log(arr.map(value => [Math.round(value)]));
// => [[4], [20], [26]]
console.log(arr.flatMap(value => [Math.round(value)]));
// => [4, 20, 26]
数组将被展平的深度级别为1.如果要从结果中删除项目,只需返回一个空数组:
const arr = [[7.1], [8.1], [9.1], [10.1], [11.1]];
// do not include items bigger than 9
arr.flatMap(value => {
if (value >= 10) {
return [];
} else {
return Math.round(value);
}
});
// returns:
// => [7, 8, 9]
除了正在处理的当前元素之外,回调函数还将接收元素的索引和对数组本身的引用。flat() 和 flatMap() 方法目前是第4阶段提案。
4. Symbol 对象的 description 属性
创建 Symbol 时,可以为其添加 description 以进行调试。有时,能够直接访问代码中的描述是有用的。此 ES2019 提议为 Symbol 对象添加了只读描述属性,该对象返回包含 Symbol description 的字符串。这里有些例子:
let sym = Symbol('foo');
console.log(sym.description); // => foo
sym = Symbol();
console.log(sym.description); // => undefined
// create a global symbol
sym = Symbol.for('bar');
console.log(sym.description); // => bar
可选的 catch 参数
不会总是使用try ... catch语句中的catch参数。请考虑以下代码:
try {
// use a feature that the browser might not have implemented
} catch (unused) {
// fall back to an already implemented feature
}
此代码中的 catch 参数没有用处。但是,它仍然应该使用为了避免SyntaxError。此提议对ECMAScript规范进行了一些小改动,允许您省略catch参数:
try {
// use a feature that the browser might not have implemented
} catch {
// do something that doesn’t care about the value thrown
}
彩蛋:ES2020 String.prototype.matchAll
matchAll() 方法是处于 ES2020 第四阶段,它针对正则表达式返回所有匹配(包括捕获组)的迭代器对象。
为了与 match() 方法保持一致,TC39选择了 matchAll 而不是其他建议的名称,例如matches 或Ruby的 scan。让我们看一个简单的例子:
const re = /(Dr\. )\w+/g;
const str = 'Dr. Smith and Dr. Anderson';
const matches = str.matchAll(re);
for (const match of matches) {
console.log(match);
}
// logs:
// => ["Dr. Smith", "Dr. ", index: 0, input: "Dr. Smith and Dr. Anderson", groups: undefined]
// => ["Dr. Anderson", "Dr. ", index: 14, input: "Dr. Smith and Dr. Anderson", groups: undefined]
以前,您必须在循环中使用 exec() 方法来实现相同的结果,这不是非常有效:
const re = /(Dr\.) \w+/g;
const str = 'Dr. Smith and Dr. Anderson';
let matches;
while ((matches = re.exec(str)) !== null) {
console.log(matches);
}
// logs:
// => ["Dr. Smith", "Dr.", index: 0, input: "Dr. Smith and Dr. Anderson", groups: undefined]
// => ["Dr. Anderson", "Dr.", index: 14, input: "Dr. Smith and Dr. Anderson", groups: undefined]
重要的是要注意尽管 match() 方法可以与全局标志 g 一起使用来访问所有匹配,但它不提供匹配的捕获组或索引位置。相比:
const re = /page (\d+)/g;
const str = 'page 2 and page 10';
console.log(str.match(re));
// => ["page 2", "page 10"]
console.log(...str.matchAll(re));
// => ["page 2", "2", index: 0, input: "page 2 and page 10", groups: undefined]
// => ["page 10", "10", index: 11, input: "page 2 and page 10", groups: undefined]
总结
在这篇文章中,我们仔细研究了ES2019中引入的几个关键特性,包括 Object.fromEntries() ,trimStart(),trimEnd() ,flat() ,flatMap(),symbol 对象的 description 属性以及可选的 catch 参数。
尽管某些浏览器供应商尚未完全实现这些功能,但由于Babel和其他JavaScript转换器,您仍然可以在项目中使用它们。
ECMAScript的发展速度近年来有所提升,并且每隔一段时间就会引入和实现新功能,因此请务必查看已完成的提案列表,以获取有关新功能的最新信息。
原文:blog.logrocket.com/5-es2019-fe…
最后照旧是一个广告贴,最近新开了一个分享技术的公众号,欢迎大家关注👇(目前关注人数可怜🤕)
