如何将一个对象推入数组,而不通过引用传递该对象?

5
我有一个包含关于国际象棋棋盘状态信息的类中的属性称为“tiles”。我试图在每次进行合法移动和游戏开始时将此属性推送到名为“moves”的数组中。但问题是,每次我推送新的“tiles”属性时,“moves”数组中先前的元素会更改为最新推送的“tiles”值。
我理解这是因为对象是通过引用传递的,因此用相同的对象替换旧元素,因为它们现在指向相同的对象,即属性“tiles”的最新值。所以,对于下面给出的代码,是否有一种方法可以将此对象推送而非引用,以便得到由于合法移动导致的每个不同的“tiles”状态。
这是我的代码片段:App.js
App = function () {
  var self = this;
  self.tiles = []; 
  // this is populated with objects from a json file
  //code to fetch json and save it to self.tiles
  //more code

  this.startGame = function () {
    //other code
    self.moves.push(self.tiles);
  };
  this.makeMove = function () {
    //other code
    self.moves.push(self.tiles);
  };
};

所以我的期望是在self.moves数组中,每个tile应该指向不同的对象而不是同一个对象。它应该包含self.tiles的不同状态,但目前,当我推动这个属性时,'moves'数组中的元素被最新的self.tiles值覆盖。
非常感谢任何解决这个问题的帮助。谢谢!

你的Tile类实现了.clone()模式吗?如果是,使用self.moves.push(self.tiles.clone())。 - Erch
我猜是的,因为在回调函数中我有以下代码。 self.tiles = wade.cloneObject(data.data.tiles); - siddube
嗨Erch,抱歉我还没有实现.clone()模式,并且对我使用的内置于ES6游戏引擎中的cloneObject函数感到困惑。但是Maheer的答案解决了问题...无论如何还是谢谢你! - siddube
“object is being passed by reference”这是一个常见的错误假设,但JavaScript是一种按值传递的语言。对象是引用类型值,但这并不等同于按引用传递。 - Felix Kling
感谢您的纠正,Felix。 - siddube
3个回答

4
你应该使用 JSON.parse(JSON.stringify()) 来克隆一个嵌套对象。你可以使用 Object.assign 来克隆浅层对象。
App = function () {
  var self = this;
  self.tiles = []; 
  // this is populated with objects from a json file
  //code to fetch json and save it to self.tiles
  //more code

  this.startGame = function () {
    //other code
    self.moves.push(JSON.parse(JSON.stringify(self.tiles)));
  };
  this.makeMove = function () {
    //other code
    self.moves.push(JSON.parse(JSON.stringify(self.tiles)));
  };
};

非常感谢Maheer!已经按照预期工作了。非常感激! - siddube

2

我稍微尝试了一下,发现可以使用展开运算符,像这样:

var a = {b: 1, c: 2}
var array1 = []

array1.push({...a})
a.c=3

console.log(array1) // [0: {b: 1, c: 2}]
console.log(a) // {b: 1, c: 3}

MDN: 对象字面量中的展开语法


1
这只是进行浅拷贝(类似于Object.assign,但不包括原型)。如果 a{level1:{level2:2}},并且您执行 ({...a}).level1.level2=8,那么您将改变 a 的值。 - HMR
所以你的意思是,“克隆”的对象的属性实际上是对a.prop1、a.prop2的引用?TIL - Andrei C

0
唯一解决您的问题的方式是传递要推送到向量中的对象的克隆。在这种情况下,通常会为您的对象编写一个clone()方法,以返回其自身的深拷贝。此方法返回的对象可以推送到数组中。

谢谢Ravi,我也会注意这个。 - siddube

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接