为什么他们的数据似乎是同步的?

时间:2011-11-21 22:54:02

标签: javascript

在javascript中,当我

var buffer = new Array();
buffer = AnotherArray;  

但奇怪的是,我所做的缓冲,结果也发生在AnotheArray上。例如,我删除了缓冲区中的一些元素,我发现它们也在AnotherArray中删除了。为什么这样,我该如何解决?

5 个答案:

答案 0 :(得分:4)

您引用的代码绝对不会导致第一行new Array()创建的数组和下一行AnotherArray以任何方式相关联。如果你看到他们之间有某种影响,那就是你没有引用过的代码。

具体来说,你的代码会创建一个数组,然后完全抛弃它,让buffer引用不同的事物(从名称来看,它似乎可能是一个数组) 。但是在第一行创建的数组丢失了。

我怀疑你可能会做这样的事情:

var buffer = new Array();
var foo = new Array();
buffer = foo;
buffer.push("Testing");
alert(foo.length); // alerts "1", not "0"

在这种情况下,在第一行创建的数组完全被丢弃,并且(在第三行)您将bufferfoo指向相同阵列。只有一个数组,但你有两个引用它。所以你通过buffer对数组的引用做了什么,你也可以通过foo引用查看同一个数组。只有一个数组,你只有两个引用它。

如果你想复制数组,请参阅下面的分界线(很长的路)。

如果您考虑一下,它就像将参考传递给函数时所发生的那样:

var f = new Array(); // Or better, you could use `[]` rather than `new Array()`
f.push("one");
bar(f);
alert(f.length);     // alerts "2"

function bar(a) {
    a.push("two");   // Here, `a` and `f` point to the **same** array
}

在那里,警报显示“2”而不是“1”,因为bar函数中的代码通过其参数列表中的a引用添加到数组中,该引用指向相同的数组作为f引用。

JavaScript具有对象类型(也称为引用类型)和基元。字符串和数字是原语,它们实际上保存在分配给变量的内存中。几乎所有其他东西都是一个对象,其中变量将引用保存到对象,而不是对象本身的副本。所以:

var a = 1;
var b = a;
b = 2;
alert(a); // "1"
alert(b); // "2"

ab包含原始数字1副本。但是:

var c = {prop: "value"};
var d = c;
d.prop = "updated value";
alert(c.prop); // "updated value"

在那里,cd指向相同的对象,因此无论对哪个(c或{ {1}})你用它来看待它。

当然:

d

由于var e = {prop: "foo"}; var f = {prop: "foo"}; f.prop = "bar"; alert(e.prop); // "foo" e指向不同的对象,因此对一个对象的更改对另一个没有影响。

保持这种直接的关键是将引用(不是对象)视为原始值。 引用只是一个随意的东西,可以让你在表中查找对象。所以虽然:

f

...在内存中产生这个:

+-------+
|   a   |
+-------+
|   1   |
+-------+

...这样的:

var a = 1;

......产生这个:

+-------+
|   c   |
+-------+              +---------------+
|  ref  |------------->| prop: "value" |
+-------+              +---------------+

因此,这个:

var c = {prop: "value"};

...产率:

+-------+
|   a   |
+-------+
|   1   |
+-------+

+-------+
|   b   |
+-------+
|   1   |
+-------+

......但是这个:

var a = 1;
var b = a;

......产生这个:

+-------+
|   c   |
+-------+
|  ref  |----\
+-------+    |
             |
             |       +---------------+
             |------>| prop: "value" |
             |       +---------------+
+-------+    |
|   d   |    |
+-------+    |
|  ref  |----/
+-------+

引用是变量所持有的,而不是对象。引用是指向对象的原语。


那你怎么办呢?好吧,大部分时间,这都是你想要的,因为大多数时候你想传递引用并引用回原始对象。但有时你想要复制一个对象。

使用数组,这很容易:使用Array#slice传递var c = {prop: "value"}; var d = c; 作为第一个参数而没有第二个参数:

0

var a = [1, 2, 3]; // An array containing 1, 2, and 3 alert(a.length); // "3" var b = a.slice(0); // Copy it alert(b.length); // "3" b.push(4); // Add a fourth element alert(b.length); // "4", it *has* changed alert(a.length); // "3", it hasn't changed 从您指定的元素开始,从源数组创建一个新数组和复制元素。由于我们说Array#slice,它会复制整个数组。请注意,它是副本,如果任何数组条目是对象的引用,就像0一样,引用被复制,而不是对象

答案 1 :(得分:1)

buffer是对AnotherArray的引用,是内存中同一对象的不同名称。

这就像是指使用全名或昵称的人 - 两种方式都可以用来“访问”个人实例。

答案 2 :(得分:1)

发生这种情况是因为这两种变量指向同一个数组。 为避免这种情况,如果您要将AnotherArray的副本分配给buffer,可以使用slice()

var buffer = AnotherArray.slice();

答案 3 :(得分:0)

有几件事正在发生......

var buffer = new Array(); // A new, empty array is created. It is
                          // accessed via buffer

buffer = AnotherArray;    // Remember that new array that buffer pointed to?
                          // It's now gone, and will be garbage collected.
                          //
                          // Now buffer is a second reference to AnotherArray.
                          // Any changes to AnotherArray are now also changes
                          // to buffer. Both buffer and AnotherArray are
                          // references to a single array in memory.

答案 4 :(得分:0)

var buffer = new Array();

创建一个新数组并使buffer指向它。

buffer = AnotherArray; 

使buffer指向AnotherArray指向的数组,因此bufferAnotherArray指向同一个数组。这是设计的,因为大多数时候你不想经历复制对象(或特别是函数)的麻烦,这是一个巨大的内存浪费。