在javascript中,当我
var buffer = new Array();
buffer = AnotherArray;
但奇怪的是,我所做的缓冲,结果也发生在AnotheArray上。例如,我删除了缓冲区中的一些元素,我发现它们也在AnotherArray中删除了。为什么这样,我该如何解决?
答案 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"
在这种情况下,在第一行创建的数组完全被丢弃,并且(在第三行)您将buffer
和foo
指向相同阵列。只有一个数组,但你有两个引用它。所以你通过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"
a
和b
包含原始数字1
的副本。但是:
var c = {prop: "value"};
var d = c;
d.prop = "updated value";
alert(c.prop); // "updated value"
在那里,c
和d
指向相同的对象,因此无论对哪个(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
指向的数组,因此buffer
和AnotherArray
指向同一个数组。这是设计的,因为大多数时候你不想经历复制对象(或特别是函数)的麻烦,这是一个巨大的内存浪费。