为啥要使用扩展运算符将变量扩展到自身?
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 copy 的data
;假设您有一个改变输入的第三方函数:
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 扩展运算符?