你可能不知道 JavaScript 扩展运算符能做什么?

2025-05-27

你可能不知道 JavaScript 扩展运算符能做什么?

如果您觉得这篇文章有用,可以订阅我的邮件列表,查看我博客上的其他文章,或者在Twitter上关注我。我还有几个正在进行的业余项目,您可能想看看:

  • ippy.io - 一款用于创建精美简历的应用程序
  • many.tools - 为设计师和开发人员提供的实用工具集合

自从 ES6 引入扩展运算符以来,它就受到了 JavaScript 社区的热烈欢迎,这当然是有原因的!它极大地简化了许多常见的对象和数组操作模式。

虽然其常见用途受到广泛赞赏和利用,但它也促进了一些稍微不那么明显的模式。

例如…

👉 1)有条件地向对象添加属性

这也许并不常见,但想象一下(无论出于何种原因)你想要有条件地向一个对象添加属性。具体来说,你想要在属性值为真时添加它们,而在属性值为空、未定义或包含假值时排除它们。你会怎么做呢?

合理的方法可能是类似如下:

const firstName = 'Harrison'
const lastName = null
const address = '123 Street Rd'
const phoneNumber = null

const userInfo = {}

if (firstName) {
  userInfo.firstName = firstName
}

if (lastName) {
  userInfo.lastName = lastName
}

if (address) {
  userInfo.address = address
}

if (phoneNumber) {
  userInfo.phoneNumber = phoneNumber
}

console.log(userInfo)

// {
//   firstName: 'Harrison',
//   address: '123 Street Rd'
// }

这种方法没有什么问题 - 但是使用扩展运算符,我们可以将条件逻辑移动到对象文字内。

结果稍微简洁了一些,而且在我看来,一旦你看过几次之后,它实际上更具可读性。

看一下:

const firstName = 'Harrison'
const lastName = null
const address = '123 Street Rd'
const phoneNumber = null

const userInfo = {
  ...firstName && { firstName },
  ...lastName && { lastName },
  ...address && { address },
  ...phoneNumber && { phoneNumber }
}

console.log(userInfo)

// {
//   firstName: 'Harrison',
//   address: '123 Street Rd'
// }

如果你之前没见过这种模式,可能需要花点时间才能理解。我会尝试解释一下:

让我们考虑对象文字中的第一行,其中应该将属性添加到对象的情况:

...firstName && { firstName }

由于firstName先前已赋值为真值'Harrison'
表达式firstName && { firstName }将返回{ firstName: 'Harrison' }。 的左侧和右侧均被&&评估为真值,因此返回右侧。

然后将此返回的对象传播到userInfo对象中,从而成功设置 firstName 属性。

接下来,我们考虑另一种情况,即尝试赋一个 false 值。我们来看对象字面量的第二行:

...lastName && { lastName }

在这种情况下,lastName为空。这意味着表达式lastName && { lastName }短路返回 的左侧&&,在本例中为null

然后我们尝试将其扩散到对象nulluserInfo。你可能认为这会导致错误,但实际上不会。

事实上,据我所知,将任何 false 值传入对象都是完全有效的语法,但不会导致对象发生任何变化。试试看:

let obj = { ...null }
console.log(obj)
// {}

let obj = { ...undefined }
console.log(obj)
// {}

let obj = { ...false }
console.log(obj)
// {}

let obj = { ...'' }
console.log(obj)
// {}

let obj = { ...0 }
console.log(obj)
// {}

let obj = { ...{} }
console.log(obj)
// {}

let obj = { ...[] }
console.log(obj)
// {}

所有这些的最终结果是,任何真值都将被添加到对象中,而任何假值都将被忽略!

为了使代码更加明确,我们可以使用相同的模式,但将真实性检查重构为其自己的函数:

const hasIfTruthy = (propertyName, property) => {
  return property && { [propertyName]: property }
}

const firstName = 'Harrison'
const lastName = null
const address = '123 Street Rd'
const phoneNumber = null

const userInfo = {
  ...hasIfTruthy('firstName', firstName),
  ...hasIfTruthy('lastName', lastName),
  ...hasIfTruthy('address', address),
  ...hasIfTruthy('phoneNumber', phoneNumber)
}

console.log(userInfo)

// {
//   firstName: 'Harrison',
//   address: '123 Street Rd'
// }

使用这种模式,您甚至可以完全改变决定某个属性是否被包含或排除的条件 - 它不一定需要仅基于真实性/虚假性。


👉 2)将数组展开为对象

所以...我还没有想到一个特别令人信服的理由让你真正这样做(如果有的话请在评论中大声说出来),但你完全可以将一个数组展开到一个对象中。

结果是将每个数组元素插入到对象中,并将键设置为其各自的数组索引。

一探究竟:

const fruitsArray = ['apple', 'orange', 'banano']

const fruitsObject = { ...fruitsArray }

console.log(fruitsObject)

// {
//   0: 'apple',
//   1: 'orange',
//   2: 'banano'
// }


👉 3)将字符串扩展为数组(或对象)

这个其实挺巧妙的,而且可能比其他的更广为人知。你可以把一个字符串展开成一个数组!

结果是一个包含字符串中各个字符的数组。

在我看来,这比常见的风格允许更令人愉快的语法'string'.split('')

这里是:

const characters = [..."apple"]

console.log(characters)

// ['a', 'p', 'p', 'l', 'e']

如果你真的想尝试一下,你甚至可以将字符串展开到一个对象中🙀

const characters = {..."apple"}

console.log(characters)

// {
//   0: 'a',
//   1: 'p',
//   2: 'p',
//   3: 'l',
//   4: 'e'
// }

孩子们,在外面一定要注意安全。


你知道 JS 扩展运算符还有什么奇特或奇妙的用法吗?欢迎在评论区留言告诉我😊

文章来源:https://dev.to/harrison_codes/3-weird-things-you-probously-didn-t-know-you-can-do-with-the-javascript-spread-operator-2fln
PREV
使用 Three.JS 制作音乐可视化工具
NEXT
数据库架构和用例 - 解释