理解JavaScript中的=
运算符做什么和不做什么很重要.
The =
operator does not make a copy of the data.
The 100 operator creates a new reference to the same data.
After you run your original code:
var a = $('#some_hidden_var').val(),
b = a;
a
和b
现在是the same object的两个不同名称.
Any change you make to the contents of this object will be seen identically whether you reference it through the a
variable or the b
variable. They are the same object.
So, when you later try to "revert" b
to the original a
object with this code:
b = a;
The code actually does nothing at all, because a
and b
are the exact same thing. The code is the same as if you'd written:
b = b;
which obviously won't do anything.
Why does your new code work?
b = { key1: a.key1, key2: a.key2 };
Here you are creating a brand new object with the {...}
object literal. This new object is not the same as your old object. So you are now setting b
as a reference to this new object, which does what you want.
To handle any arbitrary object, you can use an object cloning function such as the one listed in Armand's answer, or since you're using jQuery just use the $.extend()
function. This function will make either a shallow copy or a deep copy of an object. (Don't confuse this with the $().clone()
method which is for copying DOM elements, not objects.)
For a shallow copy:
b = $.extend( {}, a );
或者深度复制:
b = $.extend( true, {}, a );
What's the difference between a shallow copy and a deep copy? A shallow copy is similar to your code that creates a new object with an object literal. It creates a new top-level object containing references to the same properties as the original object.
If your object contains only primitive types like numbers and strings, a deep copy and shallow copy will do exactly the same thing. But if your object contains other objects or arrays nested inside it, then a shallow copy doesn't copy those nested objects, it merely creates references to them. So you could have the same problem with nested objects that you had with your top-level object. For example, given this object:
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代码中的日期),以复制这些对象,其方式与复制顶级对象的方式相同.所以更改copy.x.y
不会影响obj.x.y
.
Short answer: If in doubt, you probably want a deep copy.