2011-07-06 43 views
7

我有以下代码(我用的是jQquery libary):有人可以解释我这个JavaScript对象“复制”行为

var obj = {}; 
var objstring = '{"one":"one","two":"two","three":"three"}' 

// first console output 
console.log(objstring); 

var jsonobj = $.parseJSON(objstring); 

// second console output 
console.log(jsonobj); 

obj.key = jsonobj; 
obj.key.test = "why does this affect jsonobj? (even in the second console output)"; 

// third console output 
console.log(jsonobj); 

我的问题: 当我做obj.key = jsonobj我改​​变新的obj.key中的值。为什么jsonobj中的值也会改变?我将如何避免这种情况? (我想要一个新的jsonobj“副本”)。

我做了这个测试案例:http://jsfiddle.net/WSgVz/

+5

出色的问题和测试用例。现在这种情况非常罕见,令人难以置信的令人难过。 –

回答

3

这是因为对象是不可复制的。 obj.key属性将仅包含对该对象的引用,因此,当您将某些内容分配给obj.key.test时,其效果与分配给jsonobj.test的效果相同。

您可以使用jQuery的方法extend创建一个副本:

obj.key = $.extend({}, jsonobj); 

这将值复制到新创建的对象({})。

+3

同样值得注意的是你需要'.extend(true,{},jsonobj)'来进行深层复制(而不是浅一层复制)。 – Domenic

+0

@Domenic:好的一点,对于更复杂的对象结构来说,这很好。 – Guffa

2

因为当你做obj.key = jsonobj,没有在obj.key一些新的,复制的对象;它只是对已经存在的jsonobj的引用。所以对obj.key的更改也将更改为jsonobj,因为它们实际上是同一件事。

1

这是因为有没有复制正在进行 - 只有一个对象,它是由referenced各种变量和属性。当你做obj.key = jsonobj时,你只是将引用复制到同一个对象。

1

在JavaScript中的所有对象都通过引用复制,这意味着:

var x = {}; 
var y = x; 
x.foo = 22; // y.foo also = 22 since y and x are the same object 

如果你想obj.key != jsonobj,你需要克隆的对象。通过创建一个新的对象:

obj.key = $.parseJSON(objstring); 

或使用jQuery克隆现有的一个:

obj.key = $.extend({}, jsonobj); 
+0

但我似乎没有找到第二个日志的输出背后的答案.......... –

+0

根据Domenic的回答,第二个日志语句是错误的。如果你想要一个有效的console.log:'console.log(JSON.stringify(jsonobj))' –

5

我想解决的一小块东西是怎么回事,因为别人已经做得这么好处理JavaScript对象引用的更大的问题:

// second console output 
console.log(jsonobj); 

obj.key = jsonobj; 
obj.key.test = "why does this affect jsonobj? (even in the second console output)"; 

这是一个documented WebKit bug的结果,console.log语句在调用console.log时不输出对象,而是在稍后的一段时间。

+0

我试图让这个时候我得到的东西更加清晰,所以请解释任何-1票... – Domenic

+0

哦,好吧,这只会导致我以前错误地理解javascript如何处理对象复制/委托。感谢你指出这一点;)。 – Hans

+0

将我的-1更改为+1。在我投票的时候,你没有详细的答案。现在我的脸上有鸡蛋。 – used2could

相关问题