未引用的数组在“切片”之后不是那么未引用?

时间:2012-05-05 02:37:22

标签: javascript arrays pass-by-reference

注意:这不是公共阵列副本'问题'的数百万个重复之一,其中使用arr.slice(0)修复了这个'问题'

那就是说,我想明白为什么我会得到这个意想不到的结果:

var oldArr = [[1,2],[3,4]];
var find = oldArr[1];

var newArr = oldArr.slice(0);
console.log(newArr.indexOf(find)); //1?

//proof that newArr is NOT referenced to oldArr
newArr[0] = "Hi";
newArr[1] = "How are you?";
console.log(oldArr+" "+newArr); //"1,2,3,4 Hi,How are you?"

jsFildde Demo

如果您使用以下任何替代方案替换find,则会返回预期的-1

  • 直接使用[3,4]
  • 使用包含[3,4]
  • 的变量
  • 使用包含另一个包含[3,4]
  • 的数组的变量

我找不到任何解释为什么最后三种方法和第一个例子之间存在任何差异。据我所知,应该没有。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

在:

[[1,2],[3,4]]

创建了三个数组对象

只有外层人员slice'd。这导致“浅拷贝”。

考虑一下:

var a = [1,2]
var b = [3,4]
var c = [a,b]
var d = c.slice(0)
d[0] === a       // true, which means it is the /same/ object
d[0][0] = "Hi!"
a                // ["Hi!", 2]

快乐的编码!

答案 1 :(得分:1)

一切都按预期工作

indexOf按引用搜索而不是值,因此如果两个对象彼此不===indexOf将无法找到它们

在你的情况下:

var oldArr = [[1,2],[3,4]];
var find = oldArr[1];

var newArr = oldArr.slice(0);

find指向数组[3,4]; 所以newArray包含2个对象(两个数组)。 如果你想看看真正发生了什么,试试find.push(5)