迹忆客 专注技术分享

当前位置:主页 > 学无止境 >

您应该了解的 5 个最令人兴奋的 ES2022 功能

作者:迹忆客 最近更新:2023/01/07 浏览次数:

·ECMAScript 2022· 已经发布 2 个多月了,它为我们带来了很多令人兴奋的新特性(如果你用过就会知道)。

这些新特性很棒,有的可以优化我们的代码,有的可以提高编码质量。 朋友,你还在等什么? 让我们来看看!

1. 数组的“.at()”方法

你如何读取数组的尾部元素? 是的,我们需要以 array.length - 1 作为下标来读取。

const array = [ 1, 2, 3, 4, 5 ]
const lastEle = array[ array.length - 1 ] // 5
// 你不能那样读取
const lastEle = array[ - 1 ] // undefined

还有别的办法吗?

ES2022 提供了一个数组方法 at,可能是一个小小的改动,但是可以大大提高代码的可读性。

at 方法可以取正数或负数,这将决定它是从数组的头部还是尾部开始读取元素。

const array = [ 1, 2, 3, 4, 5 ]
const lastEle = array.at(-1) // 5
const firstEle = array.at(0) // 1

2.Top-level await

朋友们,你们喜欢使用 await 吗? 我真的很喜欢它,因为它使编写异步代码对我来说显得更加优雅和直观。

// Old Style
const getUserInfoOld = () => {
  return fetch('/getUserId')
    .then((userId) => {
      return fetch('/getUserInfo', { body: JSON.stringify({ userId }) })
        .then((userInfo) => {
        return userInfo
      })
    })
}
// await Style  
const getUserInfo = async () => {
  const userId = await fetch('/getUserId')
  const userInfo = await fetch('/getUserInfo', {
    body: JSON.stringify({ userId })
  })
  return userInfo
}

await 是一个很棒的机制,过去只能封装在 async 函数中。 随着 ES2022 的发布,我们也可以在 async 函数之外使用它了。

const mockUserInfo = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        userName: 'fatfish'
      })
    }, 1000)
  })
}
const userInfo = await mockUserInfo()
// Can we print out { userName: 'fatfish' } please?
console.log(userInfo)

es2022 Top level await

这个功能很棒,可以让我们做很多过去做不到的事情。

动态加载模块

const enStrings = await import(`/i18n/en`)

初始化数据库

const connection = await connectDB()

有条件地渲染模块

const showBlackTheme = window.location.search.includes('theme=black')

if (showBlackTheme) {
  await import('/theme/black.js')
} else {
  await import('/theme/white.js')
}

3. Object.hasOwn

我们经常需要知道对象上是否存在某个属性,并使用 in 运算符或 obj.hasOwnProperty 来这样做。 但是他们都有一些缺陷,让我们来看看。

“in”运算符

如果指定的属性在指定的对象或其原型链中,则 in-operator 返回 true

const Person = function (age) {
  this.age = age
}

Person.prototype.name = 'fatfish'

const p1 = new Person(24)

console.log('age' in p1) // true 
console.log('name' in p1) // true  pay attention here

obj.hasOwnProperty

hasOwnProperty 方法返回一个布尔值,指示对象是否具有指定的属性作为其自身的属性(而不是继承它)。

const Person = function (age) {
  this.age = age
}

Person.prototype.name = 'fatfish'

const p1 = new Person(24)

console.log(p1.hasOwnProperty('age')) // true 
console.log(p1.hasOwnProperty('name')) // fasle  pay attention here

也许 obj.hasOwnProperty 已经可以过滤掉原型链上的属性,但在某些情况下,它并不安全,会导致程序失败。

Object.create(null).hasOwnProperty('name')
// Uncaught TypeError: Object.create(...).hasOwnProperty is not a function

Object.hasOwn

不用担心,我们可以使用Object.hasOwn来规避这两个问题,比obj.hasOwnProperty方法更方便、更安全。

let object = { age: 24 }

Object.hasOwn(object, 'age') // true

let object2 = Object.create({ age: 24 })

Object.hasOwn(object2, 'age') // false  The 'age' attribute exists on the prototype

let object3 = Object.create(null)

Object.hasOwn(object3, 'age') // false an object that does not inherit from "Object.prototype"

4 私有属性和方法

以前我们用 _ 来表示私有属性,但是不安全,仍然有可能被外部修改。

class Person {
  constructor (name) {
    this._money = 1
    this.name = name
  }
  get money () {
    return this._money
  }
  set money (money) {
    this._money = money
  }
  showMoney () {
    console.log(this._money)
  }
}

const p1 = new Person('fatfish')

console.log(p1.money) // 1
console.log(p1._money) // 1

p1._money = 2 // 从外部修改私有属性 _money

console.log(p1.money) // 2
console.log(p1._money) // 2

我们可以使用 # 来实现真正安全的私有属性

class Person {
  #money=1
  constructor (name) {
    this.name = name
  }
  get money () {
    return this.#money
  }
  set money (money) {
    this.#money = money
  }
  showMoney () {
    console.log(this.#money)
  }
}
const p1 = new Person('fatfish')
console.log(p1.money) // 1
// p1.#money = 2 // We cannot modify #money in this way
p1.money = 2
console.log(p1.money) // 2
console.log(p1.#money) // Uncaught SyntaxError: Private field '#money' must be declared in an enclosing class

5. 错误原因

在 ES2022 规范中,new Error() 可以指定其错误的原因。

const readFiles = (filePaths) => {
  return filePaths.map(
    (filePath) => {
      try {
        // ···
      } catch (error) {
        throw new Error(
          `${filePath} erroe`,
          {cause: error}
        )
      }
    })
}

有时,代码块的错误需要根据其原因进行不同的处理,但错误的原因相对相似,因此能够为它们分配错误名称是很好的。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便