两个具有相同属性的对象。删除一个对象的属性有什么影响?

问题描述 投票:3回答:1

我对这两种情况感到困惑:

第一个:

let a: object = {'name': 'gavin'};
let b: object = {};
b['name'] = a['name']; // at this time. a and b are both {'name': 'gavin'};
delete a['name']; // now a is {} and b is {'name': 'gavin'}

第二个:

let a: object = {'tag': {'name': 'gavin'}};
let b: object = {};
b['tag'] = a['tag']; // at this time. a and b are both {'tag': {'name': 'gavin'}};
delete a['tag']['name']; // now a and b are both {'tag': {}}

在第二种情况下,如果我delete a['tag'],a将是{},b将是{'tag': {'name': 'gavin'}}。正如我所料,如果我删除a['tag'],b将为null,如果我删除a['tag']['name'],b将不会受到影响。为什么会出现这样的结果?

英语不是我的母语,如果我拼写错误,请不要犹豫,让我知道。

javascript
1个回答
4
投票

在第一个示例中,您将分配字符串b['name'] = a['name']。字符串在javascript中通过值传递,因此有效地在内存中创建该字符串的新副本。 a['name']在他们引用的实际内存位置方面不等于b['name']

您可以将其视为具有两个字符串副本。删除字符串时,删除一个副本,而不删除另一个副本。

在你的第二个例子中,你正在分配一个对象b['tag'] = a['tag']。对象在javascript中通过引用传递,这意味着您不是要创建对象的新副本,而是将相同的对象分配给b['tag']。所以a['name']b['name']是同一个对象。

您可以将此视为拥有一个对象的副本,其中a['tag']b['tag']都使用该单个副本。从该单个副本中删除name属性时,它不会出现在a['tag']b['tag']中,因为它们都使用同一个对象。

这个问题的答案可能有助于你理解更好的价值与对象参考https://stackoverflow.com/a/37290849/845704

编辑

或许可以将它放在透视图中,让我们将您的示例与其他变量一起使用。请记住,这与您的示例的数据结构没有什么不同,除了它是更多的代码行。

let tag_obj = {'name': 'gavin'};
let a = { 'tag': tag_obj };
let b = {};
b['tag'] = a['tag'];

// a and b both now equal { tag: { name: 'gavin'} }

console.log(a.tag === tag_object) // True, it references tag object
console.log(b.tag === tag_object) // Also true, as it references the same object.

delete a.tag.name; 

现在,如果你delete a.tag,你正在从a对象中删除一个属性。哪个不应该影响其他任何东西,因为a不等于其他任何东西。但是当你delete a.tag.name时,你正在从tag对象中删除一个属性,我们在上面的例子中将其称为tag_object。由于a.tagb.tag都引用了tag_object,他们现在都将显示没有名称属性。


没有本地“运算符”来创建对象的附加副本,但是有一些常用的方法。第一个是Object.assign,它将一个对象的属性分配给另一个对象

let j = {'tag': {'name': 'james'}};
let k = j
console.log(k === j) // Will log true, they are the same object

let a = {'tag': {'name': 'gavin'}};
let b = Object.assign({}, a);
console.log(a === b) // Will log false, a new object has been created.

现在两个对象看起来都一样。不幸的是,Object.assign创造了所谓的浅拷贝。因此,对象本身是不同的,但是对象内的任何引用都将被共享

let a = {'tag': {'name': 'gavin'}};
let b = Object.assign({}, a);
console.log(a.tag === b.tag) // Will log true, they share the same tag object

周围有一些实用程序库可以为您创建对象的深层副本。您也可以通过遍历整个对象树来递归地执行此操作。

但是,创建对象的深层副本的一种常见且相当快速的方法是使用JSON。

let j = {'tag': {'name': 'james'}};
let k = JSON.parse(JSON.stringify(j));
console.log(j === k); // Will log false, a new object has been created.
console.log(j.tag === k.tag); // Will log false, a new object has been created.

此机制首先使用JSON.stringify生成一个新字符串,此时它不再与源对象绑定。然后使用JSON.parse从该字符串生成一个全新的对象。

注意

如果使用JSON方法,则不会保留函数,因为函数无法以任何标准JSON格式进行序列化。

© www.soinside.com 2019 - 2024. All rights reserved.