javascript数组中的对象神秘地链接在一起

Objects in Javascript Arrays Mysteriously Linked Together

本文关键字:链接 在一起 对象 数组 javascript      更新时间:2023-09-26

我有以下代码。当我访问 w[1][0] 时,我只想更改该位置的对象。但是,所有对象都会更改。我假设这是因为在某种程度上,它们都指向同一个对象。我将如何解决这个问题?

 var createArray = function(dim,init){//takes an array of dimensions and the initial value of each element
    if(dim.length > 0){
        var x = new Array();
        for(var i = 0; i < dim[0]; i++)
            x[i] = createArray(dim.slice(1),init)
        return x;
    }
    return init;
}
var w = createArray([2,2],{top: false,left: false});
console.log(w);
w[1][0].left = true;
console.log(w);

在 JavaScript 中,对象是通过引用传递的,而不是通过传递的。这意味着,如果将同一对象传递给几个变量,它们都指向内存中的同一位置。这就是为什么您的init对象到处都在更改的原因。

为了防止这种情况,您需要在将对象分配给变量之前克隆对象。最简单的内置方法之一是使用 JSON,如下所示:

var copy = JSON.parse(JSON.stringify(original));

所以在你的情况下就是这样:

x[i] = createArray(dim.slice(1), JSON.parse(JSON.stringify(init)));
w[1][0].left = true;

此行正在更改对象的唯一实例。看,这一行:

var w = createArray([2,2],{top: false,left: false});

是代码中唯一通过 {} 文本创建新对象(您感兴趣的类型(的行。所有其他集合操作(newVar = init(只复制对同一对象的引用。

这听起来很烦人,但它在代码中有很多很好的用途。要修复它,您需要每次创建一个副本,以替换最后一行createArray

var myCopy = {};
for (var key in origObject) {
  if (origObject.hasOwnProperty(key)) {
    myCopy[key] = origObject[key];
  }
}
return myCopy;

请注意 - 这是一个"浅拷贝",所以它只会复制顶级属性,任何深层次的对象仍将是引用。许多 JavaScript 库都有为你创建深层副本的函数。