揭秘ES2021令人兴奋的语言特性

大家好!我是星辰编程理财。今天我分享一篇关于ES2021(ES12)的文章,它将介绍ES2021的语言特性和功能,包括WeakRefs、Logical assignment operators、Private methods and accessors (class fields)、Promise.allSettled()等等。通过故事形式以及详细的阐述和示例,带领大家一起探索这些特性的用处,作为刚入门的新手,它能让你能够在前端开发中游刃有余。废话不多说,让我们一起探索ES2021的语言特性和功能,开启前端开发的新征程吧!

相关文章

String.prototype.replaceAll()

我们经常需要对字符串进行替换操作。在 ES2021 中,引入了 String.prototype.replaceAll() 方法,它为我们提供了一种简单而强大的替换字符串的方式。

有一次,我正在开发一个社交媒体应用,用户可以在评论区留言。然而,我们面临一个问题:用户有时会在留言中使用敏感词汇,这严重违反了我们的社区准则。我们需要在用户提交评论后,将敏感词汇替换成星号。

我决定使用 replaceAll() 方法来解决这个问题。首先,我定义了一个敏感词汇数组,包含了一些常见的敏感词汇。然后,当用户提交评论后,我使用 replaceAll() 方法遍历敏感词汇数组,并将评论中的敏感词汇替换成星号。

javascript 复制代码
const sensitiveWords = ['敏感词1', '敏感词2', '敏感词3'];
const comment = '这个评论包含敏感词1和敏感词2,请注意!';

const filteredComment = comment.replaceAll(
  new RegExp(sensitiveWords.join('|'), 'gi'),
  '***'
);

console.log(filteredComment);
// 输出: 这个评论包含***和***,请注意!

通过使用 replaceAll() 方法,我能够轻松地将评论中的敏感词汇替换成了星号,这样就保护了我们的社区环境。这个方法非常简洁高效,让我能够更好地处理用户输入中的敏感内容。

Promise.any()

我们经常需要处理异步操作,而在 ES2021 中,引入了 Promise.any() 方法,它为我们提供了一种更灵活的处理多个 Promise 的方式。

有一次,我正在开发一个电商网站,其中一个功能是展示多个供应商的商品价格,并返回最低价格。我面临的问题是,每个供应商的价格请求都是异步的,我需要等待所有请求完成后,再找出最低价格。

在过去,我通常会使用 Promise.all() 来等待所有请求完成,然后进行价格比较。然而,这种方式有一个缺点,即一旦其中一个 Promise 被拒绝,整个链路就会被拒绝,导致无法获取最低价格。

幸运的是,在 ES2021 中引入了 Promise.any() 方法,它允许我们等待多个 Promise 中的任意一个被解决(resolved),并返回该 Promise 的结果。这为我解决了之前遇到的问题。

让我们来看一下我是如何使用 Promise.any() 方法来获取最低价格的例子:

javascript 复制代码
const fetchPrices = async () => {
  const promises = [
    fetchPriceFromSupplier1(),
    fetchPriceFromSupplier2(),
    fetchPriceFromSupplier3()
  ];

  try {
    const lowestPrice = await Promise.any(promises);
    console.log(`最低价格是:${lowestPrice}`);
  } catch (error) {
    console.error('获取价格失败:', error);
  }
};

fetchPrices();

通过使用 Promise.any() 方法,我可以并行地发起多个价格请求,并在任何一个请求成功后立即获取到最低价格。这让我能够更高效地处理异步操作,并且不会受到某个请求失败的影响。

WeakRefs

我们经常需要处理对象的引用和内存管理。在 ES2021 中,引入了 WeakRefs 特性,它为我们提供了一种更好地处理弱引用的方式。

有一次,我正在开发一个图片库应用,用户可以上传图片并进行管理。然而,由于图片占用内存较大,我需要在用户不再需要某张图片时,自动释放内存。这样可以避免内存泄漏和浪费。

在过去,我通常会使用手动引用计数的方式来管理对象的引用和内存释放,但这种方式很容易出错,而且不够灵活。幸运的是,ES2021 引入了 WeakRefs,它为我解决了这个问题。

让我们来看一下我是如何使用 WeakRefs 来管理图片对象的例子:

javascript 复制代码
class Image {
  constructor(url) {
    this.url = url;
    this.#ref = new WeakRef(this);
  }

  async load() {
    // 加载图片逻辑
  }

  release() {
    if (this.#ref.deref() === this) {
      // 释放图片内存
    }
  }
}

const image = new Image('https://example.com/image.jpg');
image.load();

// 用户不再需要这张图片
image.release();

通过使用 WeakRefs,我可以在图片对象不再被其他地方引用时,自动释放图片的内存。这样我就能够更好地管理内存,避免内存泄漏和浪费。

Logical assignment operators (||=, &&=, ??=)

我经常需要在处理变量赋值时进行一些逻辑操作。在 ES2021 中,引入了三个新的逻辑赋值运算符:||=&&=??=

有一天,我正在开发一个任务管理应用,用户可以创建任务并设置任务的状态。每当用户完成一个任务时,我需要将任务的状态标记为已完成。以前,我通常会使用条件语句来实现这个逻辑:

javascript 复制代码
if (!task.status) {
  task.status = 'completed';
}

然而,这种方式显得冗长而且不够简洁。幸运的是,在 ES2021 中,我可以使用逻辑赋值运算符来简化这个过程:

javascript 复制代码
task.status ||= 'completed';

通过使用 ||= 运算符,我可以在 task.status 为假值(如 nullundefined)时,将其赋值为 'completed'。这让我的代码更加简洁、易读,并且减少了冗余的条件判断。

类似地,&&= 运算符可以用于在变量为真值时进行赋值操作,而 ??= 运算符则可以用于在变量为 nullundefined 时进行赋值操作。这些逻辑赋值运算符让我能够以更简洁的方式处理变量赋值的逻辑,提升了代码的可读性和维护性。

Numeric separators

我经常需要处理大量的数字,例如金额、电话号码等。在 ES2021 中,引入了数字分隔符特性,它为我们提供了一种更可读且易于理解的数字表示方式。

有一次,我正在开发一个电商网站,其中一个功能是显示商品的价格。商品价格通常是一个较大的数字,例如 10000000,这种表示方式不够直观,不容易阅读。为了提高用户体验,我想将商品价格以更易读的方式呈现出来。

幸运的是,在 ES2021 中,我可以使用数字分隔符来增加数字的可读性。使用下划线 _ 作为数字分隔符,我可以将这个较大的数字表示为:10_000_000。这样的表示方式更加直观,让用户能够更容易地理解和识别数字的大小。

除了较大的数字外,数字分隔符还可以用于其他场景,例如电话号码、信用卡号码等。通过使用数字分隔符,我可以将这些长数字以一种更可读的方式展示给用户,提高了用户体验和界面的友好性。

Private methods and accessors (class fields)

我经常需要创建和维护复杂的类结构,以实现面向对象的编程。在 ES2021 中,引入了私有方法和访问器(私有字段)的特性,它为我们提供了一种更好地封装和保护类的内部实现细节的方式。

有一次,我正在开发一个音乐播放器应用,其中一个关键的类是 Player 类,用于控制音乐的播放。在过去,这个类的所有方法都是公开的,无论是用于内部使用的还是供外部调用的。这导致类的内部实现细节暴露给了外部,不够安全和可维护。

幸运的是,在 ES2021 中,我可以使用私有方法和访问器来解决这个问题。通过在方法名或字段名前加上 # 符号,我可以将它们标记为私有的,只能在类的内部进行访问。这样,我就能够更好地封装类的内部逻辑,保护了实现细节,同时提供了更清晰的接口供外部调用。

让我们来看一下我是如何使用私有方法和访问器的例子:

javascript 复制代码
class Player {
  #currentSong;

  constructor() {
    // 初始化播放器
  }

  #playSong() {
    // 播放当前歌曲
  }

  play() {
    this.#playSong();
  }

  #pauseSong() {
    // 暂停当前歌曲
  }

  pause() {
    this.#pauseSong();
  }
}

const player = new Player();
player.play();

通过使用私有方法和访问器,我可以将播放器类的内部实现细节隐藏起来,只暴露出必要的公共接口。这样,我可以更好地封装和保护类的内部逻辑,提高了代码的安全性和可维护性。

Promise.allSettled()

我们经常需要处理多个 Promise 对象,并在它们全部解决或拒绝后进行相应的操作。在 ES2021 中,引入了 Promise.allSettled() 方法,它为我们提供了一种更灵活和全面的处理多个 Promise 的方式。

有一次,我正在开发一个电商网站,其中一个功能是展示多个供应商的商品信息。我需要同时向多个供应商的 API 发送请求,并在所有请求完成后,获取每个供应商的商品信息。

在过去,我通常会使用 Promise.all() 方法来等待所有请求完成,并在所有请求成功后获取结果。然而,这种方式有一个缺点,即一旦其中一个请求失败,整个链路就会被拒绝,导致无法获取其他请求的结果。

幸运的是,在 ES2021 中引入了 Promise.allSettled() 方法,它允许我们等待多个 Promise 的状态全部被解决,并返回一个包含每个 Promise 结果的数组,无论是成功还是失败。这为我解决了之前遇到的问题。

让我们来看一下我是如何使用 Promise.allSettled() 方法来获取多个供应商的商品信息的例子:

javascript 复制代码
const fetchProductInfo = async () => {
  const promises = [
    fetchProductInfoFromSupplier1(),
    fetchProductInfoFromSupplier2(),
    fetchProductInfoFromSupplier3()
  ];

  const results = await Promise.allSettled(promises);

  const productInfo = results.map(result => {
    if (result.status === 'fulfilled') {
      return result.value;
    } else {
      return { error: result.reason };
    }
  });

  console.log(productInfo);
};

fetchProductInfo();

通过使用 Promise.allSettled() 方法,我可以并行地发起多个请求,并在所有请求完成后获取每个请求的结果。无论请求是成功还是失败,我都能够获取到对应的结果,而不会因为其中一个请求的失败而导致整个链路被拒绝。

在这个故事中,Promise.allSettled() 方法为我提供了一种更灵活、更全面的处理多个 Promise 的方式。我感到非常激动和满意,因为它帮助我更好地处理异步操作,提升了代码的健壮性和可靠性。

Well-formed JSON.stringify()

我们经常需要将 JavaScript 对象转换为 JSON 字符串,以便在网络传输或存储时进行数据交换。在 ES2021 中,引入了 Well-formed JSON.stringify() 特性,它为我们提供了一种更可靠的方式来序列化 JavaScript 对象。

有一次,我正在开发一个社交媒体应用,用户可以发布帖子并分享到其他平台。为了实现这个功能,我需要将帖子对象转换为 JSON 字符串,并将其发送到其他平台的 API。

在过去,我通常会使用 JSON.stringify() 方法来将对象转换为 JSON 字符串。然而,这种方式存在一些问题,特别是在处理特殊字符时。有时候,JSON.stringify() 方法会生成一些不符合规范的 JSON 字符串,导致在其他平台上解析失败。

幸运的是,在 ES2021 中引入了 Well-formed JSON.stringify() 特性,它确保了生成的 JSON 字符串始终符合规范。这让我可以更加放心地将 JavaScript 对象转换为 JSON 字符串,并进行数据交换。

让我们来看一下我是如何使用 Well-formed JSON.stringify() 特性将帖子对象转换为 JSON 字符串的例子:

javascript 复制代码
const post = {
  id: 1,
  title: 'Hello, world!',
  content: 'This is a sample post.'
};

const jsonString = JSON.stringify(post, null, 2);

console.log(jsonString);

通过使用 Well-formed JSON.stringify() 特性,我可以生成一份符合规范的 JSON 字符串,其中包括缩进和换行。这让我能够更好地阅读和调试生成的 JSON 字符串,同时确保了在其他平台上的解析成功。

AggregateError

我们经常需要处理多个 Promise 的错误。在 ES2021 中,引入了 AggregateError 类型,它为我们提供了一种更好地处理多个错误的方式。

有一次,我正在开发一个电商网站,其中一个功能是展示多个供应商的商品信息。我需要同时向多个供应商的 API 发送请求,并在有错误发生时进行相应的处理。

在过去,我通常会使用 Promise.all() 方法来等待所有请求完成,并在有错误发生时抛出一个通用的错误。然而,这种方式无法提供更详细的错误信息,也无法区分不同的错误来源。

幸运的是,在 ES2021 中引入了 AggregateError 类型,它允许我们创建一个聚合错误对象,包含了多个错误的详细信息。这为我解决了之前遇到的问题。

让我们来看一下我是如何使用 AggregateError 类型来处理多个供应商请求的错误的例子:

javascript 复制代码
const fetchProductInfo = async () => {
  const promises = [
    fetchProductInfoFromSupplier1(),
    fetchProductInfoFromSupplier2(),
    fetchProductInfoFromSupplier3()
  ];

  try {
    await Promise.all(promises);
  } catch (error) {
    if (error instanceof AggregateError) {
      for (const subError of error) {
        console.error(subError);
      }
    } else {
      console.error(error);
    }
  }
};

fetchProductInfo();

通过使用 AggregateError 类型,我可以捕获到多个请求的错误,并逐个处理每个错误。这样我就能够提供更详细的错误信息,区分不同的错误来源,并进行相应的处理。

最后:希望这些内容能够帮助你更好地理解和应用这些特性。如果你还有其他问题,欢迎继续提问!🎉

注:各版本存在重复特性可能是因为这些特性在当前版本中被初步提出,但由于一些原因未能及时成为标准的一部分。因此,在随后中,为了确保这些特性的稳定性和可用性,它们被再次列入标准。

相关推荐
崔庆才丨静觅8 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60619 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅9 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅10 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅10 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment10 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅10 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊10 小时前
jwt介绍
前端
爱敲代码的小鱼11 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax