提升 JS 解构和扩展语法的 4 种方法

2025-06-07

提升 JS 解构和扩展语法的 4 种方法

如果你是 JavaScript 的爱好者,并且喜欢阅读开发文章,你可能会和我一样,喜欢点击每一篇标题为“X 个酷炫的 JS 技巧”的文章。
我大概读过 40-50 篇这样的文章。我发现大多数非常有用的文章都与解构和展开语法有关。我想把最好的技巧整理在这里。

1. 使用索引号解构数组

解构是一种从数据集中精确提取所需内容的好方法。然而,对于数组来说,如果你需要的是后面几个索引处的属性,而你并不关心前几个索引,那么这可能会令人沮丧。

我确信您之前见过这样的语法,其中使用逗号省略属性:

const fruits = ['🍎', '🥭', '🍉', '🍋']
const [,,, lemon] = fruits
console.log(lemon) // 🍋
Enter fullscreen mode Exit fullscreen mode

在我看来,这看起来很乱。开发人员必须查看逗号的数量才能知道从数组中获取了哪些属性,而且如果需要获取几个不相邻的值,这会变得非常麻烦。

值得庆幸的是,在 JS 中,数组本质上就是对象。索引是键,数组属性是值。

const fruits = ['🍎', '🥭', '🍉', '🍋']
// {0: '🍎', 1: '🥭', 2: '🍉', 3: '🍋'}
Enter fullscreen mode Exit fullscreen mode

这意味着我们可以在数组上使用对象解构。我们可以使用想要访问的属性的索引来从数组中拉取它们。

const fruits = ['🍎', '🥭', '🍉', '🍋']
const {3: lemon} = fruits
console.log(lemon) // 🍋
Enter fullscreen mode Exit fullscreen mode

现在,开发人员可以通过检查索引来准确了解您使用了哪个属性。此外,如果您需要多个不相邻的值,也无需费力地计算它们之间的逗号数量。

2. 使用扩展和解构进行过滤

移除对象的属性非常简单。只需使用delete关键字即可。

const food = {watermelon: '🍉', apple: '🍎', mango: '🥭', fries: '🍟'}
delete food.fries
console.log(food) // {watermelon: '🍉', apple: '🍎', mango: '🥭'}
Enter fullscreen mode Exit fullscreen mode

如果您愿意修改对象,这样做没有问题。
但是,对象可能会被传递到不同的函数中,并在多个位置访问,因此突然删除一个属性可能会导致问题。
因此,通常更安全的做法是保留初始对象,并创建一个新的对象用于过滤。

我们可以通过使用解构将不需要的属性与对象的其余部分分离来实现这一点。

const food = { watermelon: '🍉', apple: '🍎', mango: '🥭', fries: '🍟' }
const { fries, ...fruits } = food
console.log(fruits) // { watermelon: '🍉', apple: '🍎', mango: '🥭' }
Enter fullscreen mode Exit fullscreen mode

请注意,与改变原始对象相比,我们现在有一个具有合适名称的新对象,可以更清楚地表明该对象现在包含的内容。

此方法的一个警告是,linters 可能会在您要删除的属性下划线(在本例中fries),因为该变量不会在任何地方被引用。

3. 可选对象构建

有时我们希望有条件地构建一个对象。当我需要向 API 发送数据时,我经常会遇到这样的困境。根据应用程序所处的状态,API 请求可能需要不同的参数。

一种方法可能是使用一些if语句。

const params = { }
if (id) params.id = id
if (pageNumber) params.pageNumber = pageNumber
await axios('https://endpoint.com/data', {params})
Enter fullscreen mode Exit fullscreen mode

这种方式虽然很好用,但很快就会变得臃肿。我个人更喜欢从一开始就实例化对象,并赋予它所需的属性。

我们可以利用当传播到对象中时错误值将被忽略这一事实来实现这一点。

const params = { id: 131, ...false }
console.log(params) // { id: 131 }
Enter fullscreen mode Exit fullscreen mode

因此,为了有条件地添加属性,我们需要检查该属性是否错误,如果是,则将其添加到我们的对象中。

const params = { id: 131, ...(pageNumber && {pageNumber}) }

// Page number falsey value
console.log(params) // { id: 131 }

// Page number truthy value
console.log(params) // { id: 131, pageNumber: 2 }
Enter fullscreen mode Exit fullscreen mode

分解一下,我们从条件属性的扩展语法开始。然后添加括号,以便对短路逻辑进行分组。

如果pageNumber是假值,逻辑&&将以假值退出,这在传播时不会向我们的对象添加任何内容。

然而,如果pageNumber是真的,短路逻辑将返回我们想要添加的属性并将其传播到我们的对象中。

因此重构 api 示例。

const params = {
  ...(id && { id }),
  ...(pageNumber && { pageNumber })
}
await axios('https://endpoint.com/data', { params })
Enter fullscreen mode Exit fullscreen mode

对我来说,这好多了。我们避免了像if语句示例那样一开始就实例化一个空对象,所有可能发送给 API 的参数都可以直接在对象上看到,而不用费力地在if语句中寻找可能性。

4. 从数组解构长度

与第一条技巧相关,你可以更进一步,解构数组的长度。
你可能会问这有什么用,但假设你需要一个大型动态数组的最后一个元素。你无法使用逗号方法或索引方法解构这个最后一个元素,因为在添加数据后,最后一个元素的索引会有所不同。因此,你可以在解构时使用 length 属性来获取最后一个元素。

const bigDynamicArray = ['','😂','😝','😁','😱','👉','🙌','🍻','🔥','🌈','','🎈','🌹','💄','🎀','','🎾','🏁','😡','👿','🐻','🐶','🐬','🐟','🍀','👀','🚗','🍎','💝','💙','👌','','😍','😉','😓','😳','💪','💩','🍸','🔑','💖','🌟','🎉','🌺','🎶','👠']

const { length, [length-1]: lastItem } = bigDynamicArray
console.log(lastItem) // 👠
Enter fullscreen mode Exit fullscreen mode

因此,我们首先提取长度。然后,我们使用计算属性名称来访问正确的索引,最后为最后一个元素命名。

我要补充的是,这条建议有点儿太聪明了,适得其反。你肯定不想让其他开发人员因为一段本来很简单却又容易理解的代码而去理解一些抽象的功能。

感谢您的阅读,如果我遗漏了什么或者您有更好的建议请告诉我,祝您 JS 愉快!

文章来源:https://dev.to/scottodea/4-ways-to-level-up-your-js-destructuring-and-spread-syntax-4eoo
PREV
使用 Markdown 和 Git 的出色笔记系统(第 1 部分)
NEXT
DevOps 工程师:获得这份工作需要什么?