删除原始对象,同时在 JavaScript 中保留它的副本

Deleting original object while preserving a copy of it in JavaScript

本文关键字:保留 副本 JavaScript 对象 原始 删除      更新时间:2023-09-26

我测试了 JavaScript 对象在 Chrome 控制台中的行为方式。假设这将在任何地方工作是否安全?:

a = new Object()
>> Object {}
b = a
>> Object {}
a.boo = "Yiss!"
>> "Yiss!"
b
>> Object {boo: "Yiss!"}
a = new Object()
>> Object {}
b
>> Object {boo: "Yiss!"}
a = b
>> Object {boo: "Yiss!"}
delete a.boo
>> true
b
>> Object {}
a
>> Object {}
delete a
>> true
a
>> Uncaught ReferenceError: a is not defined
b
>> Object {}

博士

我只想弄清楚以下陈述是否属实:在对象的多个副本中的 1 个副本中所做的修改在该对象的所有副本上都可用。如果副本或原件被删除或被新对象替换,则不会影响其他副本。

delete所做的只是从对象中删除属性。它实际上不会对属性的值执行任何操作。

这里的ab等价于window.awindow.b,因为它们是全局的,而window是全局对象。 因此,delete a等效于delete window.a,后者只是从window对象中删除a属性。

由于 JavaScript 中的变量不存储对象,而是存储对对象的引用,因此delete a所做的只是删除一个变量,该变量包含对同一对象的引用,该对象继续被 b 引用。

所以,你的问题本身是有缺陷的,因为它是基于对JavaScript中对象语义的错误理解:

如果副本或

原件被删除或被新对象替换,则不会影响其他副本。

在这种情况下,没有"副本"或"原件"之类的东西。根本没有复制对象。您只有一个对象被多个变量引用。 此外,JavaScript 中没有显式"删除对象"的概念。

这种行为是完全正常的,在所有 JavaScript 环境中都应该预料到。让我们一步一步地走过它。

创建一个新对象并将其存储在a中:

a = new Object()
>> Object {}

使b引用b执行的同一单个对象:

b = a
>> Object {}

(您似乎认为这会以某种方式"复制"对象。这是不正确的:到目前为止仍然只有一个对象,但您可以使用 ab 来引用它。您已经为单个对象指定了两个不同的变量名称。

修改 a 引用的对象(请记住,这也是 b 引用的单个对象(以具有 boo 属性:

a.boo = "Yiss!"
>> "Yiss!"

确认 b 引用的对象(与 a 引用的对象相同(已更改:

b
>> Object {boo: "Yiss!"}

使a引用新对象:

a = new Object()
>> Object {}

b仍然引用第一个对象:

b
>> Object {boo: "Yiss!"}

再次引用原始对象a

a = b
>> Object {boo: "Yiss!"}

从原始对象中删除 boo 属性:

delete a.boo
>> true

确认 boo 属性已从 b 引用的对象中删除(与 a 引用的对象相同(:

b
>> Object {}

确认 boo 属性已从 a 引用的对象中删除(与 b 引用的对象相同(:

a
>> Object {}

从全局命名空间中删除变量名 "a":

delete a
>> true

变量名 "a" 不再存在:

a
>> Uncaught ReferenceError: a is not defined

变量b仍然引用原始对象:

b
>> Object {}

你似乎认为delete破坏了价值观。它没有。相反,它会从对象中删除属性。由于全局变量是全局对象的属性,因此也可以删除它们(即,在这里,awindow.a相同(。

JavaScript 中的对象 [几乎] 总是通过引用传递。在您的情况下,ab同一个对象。

运算符delete不会删除对象或变量,而是删除属性。在您的示例中,您在全局范围内定义ab - 因此将它们视为window属性。这是delete按预期工作的唯一原因。