为啥要使用扩展运算符将变量扩展到自身?

Posted

技术标签:

【中文标题】为啥要使用扩展运算符将变量扩展到自身?【英文标题】:Why would you use the spread operator to spread a variable onto itself?为什么要使用扩展运算符将变量扩展到自身? 【发布时间】:2021-12-23 00:23:35 【问题描述】:

在 Google Getting started with Node.js 教程中他们执行以下操作

data = ...data;

在向 Firestore 发送数据的代码中。

你可以在their Github,第 63 行看到它。

据我所知,这没有任何作用。

这样做有充分的理由吗?

它是否有可能在未来进行验证,因此如果您添加自己的数据,您就不太可能执行data = data, moreData 之类的操作?

【问题讨论】:

【参考方案1】:

@Manu 的回答详细说明了什么代码行在做什么,但没有为什么它在那里。

我不知道 Google 代码示例为何使用这种方法,但我猜想如下原因(在这种情况下我自己也会这样做):

由于 javascript 中的对象是通过引用传递的,因此有必要从其组成部分重建“数据”对象,以避免原始数据对象被示例第 64 行的 ref.set(data) 调用进一步修改代码:

await ref.set(data);

例如,在 MongoDB 中,当您将对象传递给 write 或 update 方法时,Mongo 实际上会修改该对象以添加额外的属性,例如它被插入到集合中的日期时间或它在集合中的 ID。我不确定 Firestore 是否会这样做,但如果现在没有,将来可能会这样做。如果是这样,并且如果您从 Google 的示例代码调用 update 方法的原始代码继续进一步操作它最初传递的数据对象,那么该对象现在将具有可能导致意外问题的额外属性。因此,谨慎的做法是根据原始对象的属性重新构建数据对象,以避免在代码中的其他地方污染原始对象。

我希望这是有道理的——我想得越多,我就越相信这一定是原因,这实际上是一个很好的学习点。


我在此处包含 Google 代码中的完整原始函数,以防其他人将来遇到此问题,因为代码可能会更改(在撰写此答案时从 https://github.com/GoogleCloudPlatform/nodejs-getting-started/blob/master/bookshelf/books/firestore.js 复制):

// Creates a new book or updates an existing book with new data.
async function update(id, data) 
  let ref;
  if (id === null) 
    ref = db.collection(collection).doc();
   else 
    ref = db.collection(collection).doc(id);
  

  data.id = ref.id;
  data = ...data;
  await ref.set(data);
  return data;

【讨论】:

【参考方案2】:

它正在生成shallow copydata;假设您有一个改变输入的第三方函数:

const foo = input => 
  input['changed'] = true;

你需要调用它,但又不想修改你的对象,所以而不是:

data = life: 42
foo(data)

// > data
//  life: 42, changed: true 

您可以使用Spread Syntax:

data = life: 42
foo(...data)

// > data
//  life: 42 

不确定这是否是 Firestone 的特殊情况,但问题是:传播一个对象会得到该 obj 的浅表副本。

===

相关:Object copy using Spread operator actually shallow or deep?

【讨论】:

It's making a copy of data; 我可能会写 shallow copy 以表明没有进行深拷贝。 您的相关链接似乎与您回答的第一部分相矛盾。 “如果没有嵌套,它会深度复制数据。对于嵌套数据,它会深度复制最顶层的数据和嵌套数据的浅层。” 同样在这种情况下,它是什么样的副本似乎并不重要,因为新副本被分配给原始变量。所以没有一个新的变量可以对抗深/浅。

以上是关于为啥要使用扩展运算符将变量扩展到自身?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能在对象键之后使用 Javascript 扩展运算符?

为啥我们不能在 Array.map() 中使用扩展运算符,还有啥可以替代展平数组? [复制]

为啥编译器不能通过逗号运算符扩展可变参数模板的参数?

ES6 - 数组扩展(扩展运算符)

rest 参数与扩展运算符

React/Redux - 使用扩展运算符将对象添加到数组的开头