ES 2022 即将新增这6个特性,最后一个绝了。

共 4456字,需浏览 9分钟

 ·

2022-03-17 12:18

引言

新版本的 ECMA Script 将在今年六月成为标准。让我们来看看 ES2022 有什么新特性?

新功能

1. error.cause

这是一个关于错误捕获的特性,下文代码列举了过去我们常使用的三种捕获错误的方式。

async function doJob() {
  const rawResource = await fetch('/test')
    .catch(err => {
      // 下面三种是过去常用的一些捕获错误的代码方式
      
      // 1. throw new Error('下载资源失败: ' + err.message);
      
      // 2. const wrapErr = new Error('下载资源失败');
      //    wrapErr.cause = err;
      //    throw wrapErr;
      
      // 3. class CustomError extends Error {
      //      constructor(msg, cause) {
      //        super(msg);
      //        this.cause = cause;
      //      }
      //    }
      //    throw new CustomError('下载资源失败', err);
    })
}

await doJob(); // => Uncaught Error: 下载资源失败: Failed to fetch


过去的捕获错误的写法比较复杂,而且开发人员对具体使用哪个属性来获取错误的上下文没有达成共识。

新特性是在 Error 构造函数上添加一个附加选项参数 cause,其值将作为属性分配给错误实例。因此,可以将错误链接起来。

async function doJob() {
  const rawResource = await fetch('/test')
    .catch(err => {
      throw new Error('下载资源失败', { cause: err });
    });
}

try {
  await doJob();
} catch (e) {
  console.log(e);
  console.log('Caused by', e.cause);
}
// Error: 下载资源失败
// Caused by TypeError: Failed to fetch

2. Top-level await

我们现在可以在模块的顶层使用 await, 并且不再需要配合 async函数使用。

Top-level await 可以在实际生产中有以下用途。

  • 「动态加载模块」
const strings = await import(`/i18n/${navigator.language}`);

这允许模块使用运行时值来确定依赖关系。这对于开发/生产拆分、国际化、环境拆分等非常有用。

  • 「资源初始化」
const connection = await dbConnector();

允许模块表示资源。

  • 「依赖回退」
let jQuery;
try {
  jQuery = await import('https://cdn-a.com/jQuery');
} catch {
  jQuery = await import('https://cdn-b.com/jQuery');
}

依赖发生故障时,可以回退到旧版本,防止程序崩溃。

3. Object.hasOwn(obj, propKey)

Object.hasOwn() 方法是比 Object.prototype.hasOwnProperty() 方法更加 「便捷」「安全」 的策略。

例如 Object.create(null) 创建一个不继承自 Object.prototype 的对象,使 hasOwnProperty 方法无法访问。

Object.create(null).hasOwnProperty("foo")
// Uncaught TypeError: Object.create(...).hasOwnProperty is not a function

「Object.hasOwn(obj, propKey)」 使用案例。

let object = { foo: false }
Object.hasOwn(object, "foo") // true

let object2 = Object.create({ foo: true })
Object.hasOwn(object2, "foo") // false

let object3 = Object.create(null)
Object.hasOwn(object3, "foo") // false

4. RegExp match indices

正则表达式,继 /i /m /g 之后,在匹配模式上新加入了 /d,使用 /d 之后,当我们再使用exec() 方法时,返回值会增加一个新的属性 indices

简单回顾下exec() 方法。

相比于常见的 search() test()而言,exec() 匹配字符串的信息更丰富,它返回一个数组,其中存放匹配的结果,如果未找到匹配,则返回值为 null

let regx = /a+(?z)?/g; 
let string = "xaaaz"
let result = regx.exec(string);
// ['aaaz''z', index: 1, input: 'xaaaz', groups: {Z:'z'}]

(?)「ES 2018」 加入的正则语法,允许我们把部分正则内容进行 命名 并且 分组,上述例子中,/a+(?z)?/g表示匹配至少一个 「a」 以及 「0」 个或者 「1 个 z」 ,其中包含一个命名为 「Z」 的捕获组,配合 exec() 方法使用时,我们可以直接获取到捕获组的信息:result.groups,如果正则中没用使用捕获组的正则语法,则 「groups」「undefined」

尽管 exec() 返回值提供了 「index 属性」 来展示首次匹配的索引位置,「groups 属性」 提供了捕获组的信息,但在一些更高级的场景中,这些信息可能并不足够。例如,「语法高亮显示」 的实现不仅需要匹配的索引,还需要单个捕获组的开始和结束索引,即上述例子中 Z 捕获组的索引信息。

新特性中,使用 /d匹配模式时,exec() 方法的返回值会增加一个新的属性 indices

const re = /a+(?z)?/d;
const s = "xaaaz";
console.log("匹配结果:", re.exec(s));
//['aaaz''z', index: 1, input: 'xaaaz', groups: {Z:'z'}, indices: [[1,5],[4,5]]

indices属性包含了捕获组的信息,其中,**[ 1 , 5 ]** 为 aaaz 全部字符串的匹配信息,**[ 4 , 5 ]** 为 Z 捕获组的匹配索引信息。

5. New members of classes
  • 「简易变量声明」

「class」 支持在 constructor 外部直接声明变量,过去我们必须在内部声明。

class Cat {
  gender = 'female'
}
let cat = new Cat()
cat.gender // female

  • 「私有变量和私有方法」

封装是面向对象编程的核心原则之一。它通常使用可见性修饰符来实现,例如 private or public

「class」 的最近改动里加入了 #,用来将类中的变量、方法或访问器标记为私有,从外部访问私有化的内容,会直接报错。

class Cat {
  #name = 'kitty'
  gender = 'female'

  setName = () => {
    this.#name = 'jack'
      console.log(this.#name)
  }

  #setGender = () => {
    this.gender= 'male'
  }
}
let cat = new Cat()
cat.#name // SyntaxError
cat.gender // 'female'
cat.setName() // 'jack'
cat.#setGender // SyntaxError

  • 「私有字段的存在性检查」

由于尝试访问对象上不存在的私有字段会报错从而引发程序异常,因此需要能够检查对象是否具有给定的私有字段。

「class」 引入了关键词 in 来解决访问私有变量直接报错的问题。

class Example {
  #field

  static isExampleInstance(object) {
    return #field in object;
  }
}
const ex = new Example()
Example.isExampleInstance(ex) // true
Example.isExampleInstance({}) // false

isExampleInstance 方法可以判断 object 是否包含 #field

6. at()

这个特性过去我们聊过了,\# JS即将发布数组的4个新特性,学会了拿去吹牛[1]

.at()支持我们读取给定索引处的元素。它可以接受负索引来从给定数据类型的末尾读取元素。

过去我们需要这样来获取数组末尾元素:

const arr = [1,2,3,4,5]; 
arr[arr.length-1] // 5

现在 at() 可以轻松完成任务:

const arr = [1,2,3,4,5]; 
arr.at(-1) // 5

代码的语义会更直观更清爽,非常的方便!

支持类型:

  • String
  • Array
  • Typed Array

如果对你有帮助的话,希望各位朋友点赞关注收藏,你的鼓励就是我们继续推广「Javascrpit」语言新特性的动力。

原文地址:https://juejin.cn/post/7073285958791069704


长按下面二维码添加哥】微信

  1. 回复资料,免费获取鬼哥整理的高级进阶资料
  2. 回复面试题,免费获取鬼哥整理的大厂面试题
  3. 获取鬼哥免费简历指导/大厂内推机会


浏览 68
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报