了解=
JavaScript 中的运算符做什么和不做什么很重要。
该=
运营商不会使拷贝数据。
在=
操作创建一个新的参考到相同的数据。
运行原始代码后:
var a = $('#some_hidden_var').val(),
b = a;
a
并且b
现在是同一个对象的两个不同名称。
无论您是通过a
变量还是通过变量引用它,您对该对象的内容所做的任何更改都将被相同地看到b
。它们是同一个对象。
因此,当您稍后尝试使用以下代码“恢复”b
到原始a
对象时:
b = a;
代码实际上什么都不做,因为a
和b
是完全相同的东西。代码与您编写的代码相同:
b = b;
这显然不会做任何事情。
为什么你的新代码有效?
b = { key1: a.key1, key2: a.key2 };
在这里,您将使用{...}
对象字面量创建一个全新的对象。这个新对象与您的旧对象不同。因此,您现在将设置b
为对这个新对象的引用,它可以执行您想要的操作。
要处理任意对象,您可以使用对象克隆功能,例如 Armand 的答案中列出的功能,或者因为您使用的是 jQuery,所以只需使用该$.extend()
功能。此函数将制作对象的浅拷贝或深拷贝。(不要将此与用于复制 DOM 元素而非对象的$().clone()
方法混淆。)
对于浅拷贝:
b = $.extend( {}, a );
或深拷贝:
b = $.extend( true, {}, a );
浅拷贝和深拷贝有什么区别?浅拷贝类似于您使用对象字面量创建新对象的代码。它创建一个新的顶级对象,其中包含对与原始对象相同的属性的引用。
如果你的对象只包含像数字和字符串这样的原始类型,深拷贝和浅拷贝将做完全相同的事情。但是,如果您的对象包含嵌套在其中的其他对象或数组,那么浅拷贝不会复制这些嵌套对象,它只会创建对它们的引用。因此,嵌套对象可能会遇到与顶级对象相同的问题。例如,给定这个对象:
var obj = {
w: 123,
x: {
y: 456,
z: 789
}
};
如果您对该对象进行浅拷贝,则x
新对象的属性x
与原始对象相同:
var copy = $.extend( {}, obj );
copy.w = 321;
copy.x.y = 654;
现在您的对象将如下所示:
// copy looks as expected
var copy = {
w: 321,
x: {
y: 654,
z: 789
}
};
// But changing copy.x.y also changed obj.x.y!
var obj = {
w: 123, // changing copy.w didn't affect obj.w
x: {
y: 654, // changing copy.x.y also changed obj.x.y
z: 789
}
};
您可以通过深拷贝来避免这种情况。深层复制递归到每个嵌套对象和数组(以及 Armand 代码中的 Date)中,以与制作顶级对象副本相同的方式制作这些对象的副本。所以改变copy.x.y
不会影响obj.x.y
.
简短回答:如果有疑问,您可能需要深拷贝。