Javascript混合内存地址? (重置数组不起作用)

时间:2018-05-18 01:42:52

标签: javascript

我已经解决了这个问题,但它需要一个O(N)解决方案。我的解决方案似乎也没有考虑到实际情况。任何人都可以解释为什么会这样吗?

在我写的一个简单的程序中(tic tac toe game), 我有一个“析构函数”功能,可以在游戏重置时重置所有变量。

特别是,我有两个“全局”变量(我知道块范围)。 我将其中一个设置为伪静态变量来重置“游戏板”。

var board = [11,12,13,21,22,23,31,32,33];

我用它来跟踪棋盘上占用的空间。

现在,当我重新启动游戏以破坏函数时,我使用了一个伪初始化的伪静态变量。

var staticBoard = [11,12,13,21,22,23,31,32,33];

因此,在使用staticBoard在这样的函数中重置板时,板会更新。

function destructor(){
   board = staticBoard;
};

这适用于游戏的前几次迭代,但是后来在船上将无法更新,并且无论我多少次尝试析构函数都会保持不变。

我试过了。board = []; board = staticBoard;。 但我会得到相同的结果。 最终,我认为javascript以某种方式混合了两个变量的内存地址,所以不是将它们设置为等于另外我做了这个。

function destructor(){
board = [];
staticBoard.forEach(function(element){
   board.push(element);
});

这很有效,问题就停止了。

任何人都可以解释一下,如果可能的话还能提供更好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

这是因为当您执行board = staticBoard时,您不会复制任何数据,而只需指定对相同数组的引用。简单说明:

xs = [1,2,3]
ys = xs
ys[2] = 4
xs //=> [1,2,4]

相反,你应该:

  • 使用sliceboard = staticBoard.slice(0)
  • 对阵列进行浅层复制
  • 分配到文字数组:board = [11,12,13,21,22,23,31,32,33]

您可能希望使用Object.freeze来阻止staticBoard完全变异(但请注意,突变不会出错,只会无声地失败):

xs = Object.freeze([1,2,3])
ys = xs.slice(0)
xs[2] = 4
ys[2] = 5
xs //=> [1,2,3]
ys //=> [1,2,5]

然而,浅复制和冻结只能很好地工作,因为数组包含不可变的数字。如果内容是可变的,它也不会起作用:

xs = Object.freeze([[1]])
ys = xs.slice(0)
ys[0][0] = 2
xs //=> [[2]]
ys //=> [[2]]

答案 1 :(得分:0)

在Javascript中,对象变量本质上是指向内存位置的指针。当你这样做

obj1 = obj2

您只是将obj2内存位置分配给obj1 - 内存中的对象不会被复制。您应该创建一个数组的副本,这会创建一个 new 对象:

function destructor(){
   board = staticBoard.slice(0);
};

这样,位于staticBoard的对象永远不会变异,所以你可以一遍又一遍地引用它来获得原始电路板的新副本。

你也可以使用你发现的forEach方法,但这有点难看; slice(0)更简洁。