ES2019 中的 JavaScript 新特性

JavaScript 从成立之初就已经走了很长一段路,提供了许多新的功能,这些功能是专门设计来使该语言更加人性化和提升效率。以下是我最近发现的一些有趣的JavaScript 新增内容。其中一些功能已在 Node,Chrome,Firefox 和 Safari 中可用,而其他功能仍处于建议阶段。

Optional chaining (可选链)

Optional chaining 可选链使用 ?. 操作符来表示,Optional Chaining 使我们能检查一个对象上面是否存在某属性。其它一些语言有类似的特性。例如 C# 有 Null Conditional 操作符。而 JavaScript 的 Optional chaining 在需要深度访问嵌套对象属性时就特别有用。

当我们在访问对象的属性前,我们需要用 ?. 操作符来确定该属性是否存在。

首先看看下面代码:

1const users = [ 2 { 3 name: "Olagunju Gbolahan", 4 occupation: "Software Developer", 5 sayName(){ 6 console.log(`my name is ${this.name}`); 7 }, 8 address: { office: "New York" } 9 }, 10 { name: "Olawaseyi Moses" }, 11 { name: "Tunde Ednut" } 12];

在该数组对象中,第二个对象是 secondUser:

const secondUser = users[1];

我们需要知道该用户的办公室地址,在没有 Optional chaining 之前,我们需要使用一种很低效的方式来验证该属性是否已存在:

1const theAddress = secondUser.address && secondUser.address.office; 2console.log(theAddress); // undefined

如果我们是一个深度嵌套的对象,那就必须通过 && 操作符来判断每一层的对象是否有效:

但是有了 optional chaining ,代码便可简化如下:

1const theAddress = secondUser?.address?.office; 2console.log(theAddress); // undefined

我们还可以使用 optional chaining 来确认对象的某个方法是否存在:

1const firstUser = users[0]; 2console.log(firstUser.sayName?.()); // 我的名字是 Olagunju Gbolahan

如果方法名不存在的话,它会简单的返回 undefined :

console.log(firstUser.sayOccupation?.()); // undefined

目前该特性尚未添加到 JavaScript 规范中,目前还处于草案建议阶段

你可以通过 babel-plugin-proposal-optional-chaining 这个插件来实现相同功能。

你也可以阅读 《Optional Chaining 特性进入 Stage 3,TypeScript 跟进》 这篇文章来了解更多关于该特性的进展。

Optional catch binding (可选的错误捕获绑定)

当我们事先知道错误将是什么,并且我们不希望冗余未使用的变量时,此功能将派上用场。 

首先看看常规的 try 和 catch 的代码块:

1try { 2 const parsedJsonData = JSON.parse(obj); 3} catch (error) { 4 //obj 变量在使用时没有进行定义 5 console.log(obj); 6}

而通过错误捕获绑定,我们无需提供未使用的变量,特别是当我们已经为 try 块提供默认处理的情况下:

1function getName () { 2 let name = "Gbolahan Olagunju"; 3 try { 4 name = obj.details.name 5 } catch {} 6 console.log(name); 7}

管道操作符

这是对 JavaScript 的拟议补充之一,目前处于第1阶段。本质上,它有助于使对同一参数的多个函数调用可读。

它通过将表达式的值作为参数传递给函数来实现。

在没有管道运算符的情况下调用以下函数|>

1const capitalize = (input) => input[0].toUpperCase() + input.substring(1); 2const removeSpaces = (input) => input.trim(); 3const repeat = (input) => `${input}, ${input}`; 4 5const withoutpipe = repeat(capitalize(removeSpaces(' i am gbols '))); 6console.log(withoutpipe); // I am gbols, I am gbols

而通过管道操作符,可读性大幅提升:

1const withpipe = ' i am gbols ' 2 |> removeSpaces 3 |> capitalize 4 |> repeat; 5console.log(withpipe); // // I am gbols, I am gbols

String.trimStart 和 String.trimEnd

这两个方法在之前被命名为 trimRight 和 trimLeft,但在 ES2019 中将名字修改为 trimStart 和 trimEnd ,表述更加直观:

示例代码:

1let message = " Welcome to LogRocket "; 2message.trimStart(); // "Welcome to LogRocket " 3message.trimEnd(); // "Welcome to LogRocket";

Object.fromEntries

在聊 Object.fromEntries 之前,有必要先看看 Object.entries.

Object.entries 是在 ES2017 规范中引入的,用于将对象转成数组,并可通过数组相关的函数进行访问。

示例代码:

1const devs = { 2 gbols: 5, 3 andrew: 3, 4 kelani: 10, 5 dafe: 8, 6}; 7const arrOfDevs = Object.entries(devs); 8console.log(arrOfDevs); 9//[ 10// ["gbols", 5] 11// ["andrew", 3] 12// ["kelani", 10] 13// ["dafe", 8] 14//]

然后我们可以使用 filter 方法来获取数组中超过 5 年经验的对象:

1const expDevs = arrOfDevs.filter(([name, yrsOfExp]) => yrsOfExp > 5); 2console.log(expDevs); 3//[ 4// ["kelani", 10] 5// ["dafe", 8] 6//]

那么就会有一个新的问题:没有一个简单的方法将最新的数组重新变成对象。通常我们需要自己编写代码将数组变成对象:

1const expDevsObj = {}; 2for (let [name, yrsOfExp] of expDevs) { 3expDevsObj[name] = yrsOfExp; 4} 5console.log(expDevsObj); 6//{ 7 //dafe: 8 8 //kelani: 10 9//}

但是现在通过 Object.fromEntries 就可以把这个过程极大简化:

1console.log(Object.fromEntries(expDevs)); 2//{ 3 //dafe: 8 4 //kelani: 10 5//}

Flat

很多使用我们需要处理深度嵌套的数组,这个时候将数组展平就特别重要。

先看看如下代码:

1const developers = [ 2 { 3 name: 'Gbolahan Olagunju', 4 yrsOfExp: 6, 5 stacks: ['Javascript', 'NodeJs', ['ReactJs', ['ExpressJs', 'PostgresSql']]] 6 }, 7 { 8 name: 'Daniel Show', 9 yrsOfExp: 2, 10 stacks: ['Ruby', 'Jest', ['Rails', ['JQuery', 'MySql']]] 11 }, 12 { 13 name: 'Edafe Emunotor', 14 yrsOfExp: 9, 15 stacks: ['PHP', 'Lumen', ['Angular', 'NgRx']] 16 } 17]; 18 19const allStacks = developers.map(({stacks}) => stacks); 20console.log(allStacks); 21// [ 22// ['Javascript', 'NodeJs', ['ReactJs', ['ExpressJs', 'PostgresSql']]] 23// ['Ruby', 'Jest', ['Rails', ['JQuery', 'MySql']]] 24// ['PHP', 'Lumen', ['Angular', 'NgRx']] 25// ]

allstacks 变量包含深度嵌套的数组,为了将该数组展平,我们可以使用 Array.prototype.flat 方法。

示例代码:

1const flatSingle = allStacks.flat(); 2console.log(flatSingle); 3//[ 4// "JavaScript", 5// "NodeJs", 6// ['ReactJs', ['ExpressJs', 'PostgresSql']]] 7// "Ruby", 8// "Jest", 9// ['Rails', ['JQuery', 'MySql']]] 10// "PHP", 11// "Lumen" 12// ["Angular", "NgRx"] 13//]

从上面代码可以推断出数组被展平了一层深,这是 array.prototype.flat 的默认参数。

我们可以向flat方法传递一个参数,以确定要展平的程度。

defaults 参数的值为1。为了完全展平数组,我们可以传递一个无穷大的参数。参数 infinity 使数组完全变平,与数组的深度无关。

示例代码:

1const completelyFlat = allStacks.flat(Infinity); 2console.log(completelyFlat); 3//[ 4// "JavaScript", 5// "NodeJs", 6// "ReactJs", 7// "ExpressJs", 8// "PostgresSql", 9// "Ruby", 10// "Jest", 11// "Rails", 12// "JQuery", 13// "MySql", 14// "PHP", 15// "Lumen", 16// "Angular", 17// "NgRx" 18//]

FlatMap

FlatMap 相当于将 map 方法和 flat 方法合并起来,并默认使用深度为 1 的新方法。相当于是以更简洁的代码实现两种逻辑的组合。

下面是一个简单使用 map 和 flatMap 的代码:

1let arr = ['my name is Gbols', ' ', 'and i am great developer']; 2console.log(arr.map(word => word.split(' '))); 3//[ 4// ["my", "name", "is", "Gbols"], 5// ["", ""], 6// ["and", "i", "am", "great", "developer"] 7//] 8 9console.log(arr.flatMap(word => word.split(' '))); 10//[ "my" 11// "name" 12// "is" 13// "Gbols" 14// "" 15// "" 16// "and" 17// "i" 18// "am" 19// "great" 20// "developer" 21//]

总结

在这篇文字中,我们详细介绍了一些 JavaScript 最新添加的新特性,这些新的特性通过减少冗长的代码以及提升代码的可读性来增强了开发者的体验。不过还有很多新的特性在本文中没有涉及,欢迎大家补充和分享。

本文翻译自 https://blog.logrocket.com/new-es2019-javascript-features-every-developer-should-be-excited-about/

欢迎关注我的个人公众号 —— 红薯胡说

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

一篇文章带你了解JavaScript日期

日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用