我有一个包含20个对象的数组BaseObjects,名为ArrayBaseObjects。 用户调用一个对象,它在UI中加载,然后他对属性进行更改。 像这样:
var ArrayBaseObjects = new Array();
var CurrentObject = null;
function OpenRecord (TheIndex) {
CurrentObject = ArrayBaseObjects[TheIndex];
}
function RecordChanges() {
// bunch of statements that make changes to CurrenObject
CurrentObject.CrazyStuff = NewValue;
}
问题是,当用户对CurrentObject进行更改时,它还会更改ArrayBaseObjects中ORIGINAL对象的值。
我不明白为什么?当我写CurrentObject = ArrayBaseObjects[TheIndex];
为什么更改CurrentObject也会影响ArrayBaseObject中对象的值?
我希望比较orignal对象和用户更改的CurrentObject之间的值,但它们总是相同的!我需要做些什么改变才能按照我想要的方式工作?
感谢您的解释。
答案 0 :(得分:2)
JavaScript中的所有内容都是通过引用传递的。这意味着除非您明确克隆对象,否则将对象分配给新变量意味着现在您有两个指向同一对象的变量,并且从第二个变量中可以看到通过一个变量对该对象所做的更改。
关于如何解决这个问题的答案,你想要的是clone
对象。然而,以优雅的方式执行并不一定是一件微不足道的事情。
幸运的是,那里的JavaScript忍者已经做了很多努力。我建议使用jQuery这是一个很好的extend()
方法,您可以指定它来执行deep copy。这可以确保克隆对象中的所有数据,而不仅仅是顶级引用。
有关详细信息,请参阅this question。
在你的情况下,你会像这样使用它:
var ArrayBaseObjects = [];
var CurrentObject = {};
function OpenRecord (TheIndex) {
// This will perform a deep copy of all elements of the ArrayBaseObjects[TheIndex]
// into CurrentObject
jQuery.extend(true, CurrentObject, ArrayBaseObjects[TheIndex]);
// You could also call it like this, if you didn't need the CurrentObject variable:
// var clonedObject = jQuery.extend(true, {}, ArrayBaseObjects[TheIndex]);
}
function RecordChanges() {
// bunch of statements that make changes to CurrenObject
CurrentObject.CrazyStuff = NewValue;
}
答案 1 :(得分:1)
原因是变量持有对象的引用而不是对象本身。
声明
CurrentObject = ArrayBaseObjects[TheIndex];
使CurrentObject
的值与ArrayBaseObjects[TheIndex]
的值相同。这两个值都是同一对象的引用或指针。虽然有两个变量,但这里只有一个对象。您可以通过任一变量更改此单个对象的属性,并通过另一个变量“看到此更改”。
这一切都归结为理解变量和对象之间的区别。在JavaScript中很常见的是引用具有多个变量的一个对象。只要将对象分配给变量,或将对象作为参数传递给函数,就会发生这种情况。
这是一个简单的测试:
var a = {x:1, y:2};
var b = a;
b.x = 5;
alert(a.x); // 5
为什么?
+---------+
a ----------> | x [ 5 ] |
| y [ 2 ] |
+---------+
^
|
b -----------------+
一个对象,两个变量。
答案 2 :(得分:0)
这是因为将ArrayBaseObjects [TheIndex]分配给CurrentObject正在分配引用。请参阅此处了解如何“克隆”对象:
What is the most efficient way to deep clone an object in JavaScript?