Javascript 更改初始对象';s值

Javascript 更改初始对象';s值,javascript,javascript-objects,shuffle,slice,Javascript,Javascript Objects,Shuffle,Slice,我试图理解JavaScript对象的一个困惑点。具体地说,我感兴趣的是找到导致对象引用中断的原因(如果有的话) 为了演示这种现象,我提供了Chrome的JavaScript控制台的一些输出的副本。请注意,我在这里使用的是数组,但是考虑到JS中数组和对象之间的细微差别,我们希望对象的行为类似。为了清楚起见,我添加了一些评论 // Set x to some array literal > x = [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] // Set y

我试图理解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
如上所示,
x
y
都输出预期值。现在,我使用一个名为
shuffle
(在这个问题的底部指定)的函数来洗牌x的值

同样,一切都如上面所预期的那样工作。变量
x
y
保持对同一对象的引用。然而,当我们重复这个操作时,结果是奇怪的

  // 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
下面是改编自的随机播放功能。它的目的是洗牌数组的内容(参数
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);
}
从那以后,我通过重写我的shuffle函数修复了这个问题。然而,我仍然想了解发生了什么。为了快速查看正在运行的代码,我做了一个简单的介绍


有什么想法吗?非常感谢您抽出时间。

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

因此,第一次调用shuffle时,在循环中修改数组
x=y=r1=r2
。然后在最后一行复制它,并将其分配给x。现在
x!==y
,但它们包含完全相同的元素。您可以在第一次调用洗牌后执行以下操作:

下次调用shuffle时,您正在对所创建的
x
副本执行shuffly操作,并且
y
未被触及。

.slice()
创建数组的浅层副本,因此您正在使用新数组覆盖
x

// The original was shuffled, but now `x` is a new Array
x = shuffle(x);
这就是为什么
y
显示了第一次洗牌(因为您还没有对其进行切片),但此后就没有了。随后的洗牌是在被覆盖的
x
上进行的,并且
y
仍然引用原始的洗牌


如果要截断原始数组,只需更改其
.length

因此,与此相反:

return r2.slice(0,n);
这样做:

r2.length = n;
…尽管您当前没有向
n
传递任何内容

r2.length = n;