我试图了解我对JavaScript对象的困惑。特别是,我有兴趣查找导致对象引用中断的内容(如果有的话)。

为了演示这种现象,我提供了Chrome浏览器JavaScript控制台的一些输出副本。请注意,我在这里使用数组,但是鉴于JS中数组和对象之间的细微差别,我们希望对象的行为类似。为了清楚起见,我添加了评论。

  // Set x to some array literal
> x = [1, 2, 3, 4, 5]
  [1, 2, 3, 4, 5]

  // Set y to x
> y = x
  [1, 2, 3, 4, 5]

> x
  [1, 2, 3, 4, 5] // as expected

> y
  [1, 2, 3, 4, 5] // as expected

如上所述,xy都输出期望值。现在,我使用称为shuffle(在此问题底部指定)的函数对x的值进行混洗。
  // Shuffle x
> x = shuffle(x)
  [5, 1, 4, 2, 3]

> x
  [5, 1, 4, 2, 3] // x changes as expected

> y
  [5, 1, 4, 2, 3] // y changes as expected

同样,一切都按上述预期进行。变量xy保留了对同一对象的引用。但是,当我们重复此操作时,结果很奇怪。
  // Shuffle x
> x = shuffle(x)
  [3, 1, 5, 4, 2]

> x
  [3, 1, 5, 4, 2] // x changes as expected

> y
  [5, 1, 4, 2, 3] // y didn't change this time

以下是改编功能,改编自here。其目的是将数组的内容(参数r1)改组,并返回混合数组的前n项。
function shuffle(r1,n) {

  var i = r1.length, j, tempi, tempj, r2;
  r2 = r1;

  while (--i) {
    j = Math.floor(Math.random() * (i + 1));
    tempi = r2[i];
    tempj = r2[j];
    r2[i] = tempj;
    r2[j] = tempi;
  }

  return r2.slice(0,n);
}

从那以后,我通过重写基于this function的随机播放功能解决了该问题。但是,我仍然想了解发生了什么。为了快速查看运行中的代码,我编写了一个jsFiddle

有任何想法吗?感谢您的宝贵时间。

最佳答案

如果删除.slice(0,n);,它将按照您期望的方式运行。 slice创建一个新数组。

因此,第一次调用shuffle时,在循环中您将修改数组x = y = r1 = r2。然后在最后一行复制它,并将其分配给x。现在为x !== y,但它们包含的元素完全相同。您可以在第一次调用shuffle:后添加test that they are distinct objects

下次调用shuffle时,将对您制作的x的副本进行混洗,而y保持不变。

10-05 20:54
查看更多