ES13 (ECMAScript 2022) 已经发布很久了,并且更新了许多有用的功能。
在这篇文章中,我想与大家分享 5 种我最喜欢的技术,这些技术是我已经开始在工作中实施的。
1. 顶级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
- }
“async”函数并不是唯一可以使用“await”的地方;你甚至可以这样使用它,这真是太神奇了。
- 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)
这个功能非常棒,可以让我们做很多以前做不到的事情。
1.动态加载模块
const enStrings = await import(`/i18n/en`)
2.初始化数据库
const connection = await connectDB()
3. 有条件渲染模块
- const showBlackTheme = window.location.search.includes('theme=black')
-
- if (showBlackTheme) {
- await import('/theme/black.js')
- } else {
- await import('/theme/white.js')
- }
2. Object.hasOwn
我们经常需要知道对象上是否存在某个属性。怎么做?
“in”或“obj.hasOwnProperty”是用于此目的的两种最常用的方法。
但它们都有一些缺陷,让我们来看看。
“in”运算符
如果指定的属性位于指定的对象或其原型链中,则 in 运算符返回 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"
3. 数组“.at()”方法
我们应该如何从数组的末尾开始获取其中的元素呢?
是的,我们需要以“array.length — 1”作为下标来读取。
- const array = [ 1, 2, 3, 4, 5 ]
- const lastEle = array[ array.length - 1 ] // 5
- // You can't read like that
- 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
4. Error cause
在ES2022规范中,new Error()可以指定其错误的原因。
- const readFiles = (filePaths) => {
- return filePaths.map(
- (filePath) => {
- try {
- // ···
- } catch (error) {
- throw new Error(
- `${filePath} erroe`,
- {cause: error}
- )
- }
- })
- }
有时,代码块的错误需要根据其原因进行不同的处理,但错误的原因相对相似,因此,能够为它们分配错误名称是很棒的。
5. 私有槽位及方法
过去,我们使用“_”来表示私有属性,但它并不安全,仍然可能被外部修改。
- 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 // Modify private property _money from outside
-
- 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 enclosin