在下面的游戏代码中:即使使用了 javascript new
关键字来创建一个新对象来保存下一个状态对象,应用于下一个状态对象的方法仍然引用第一个-创建下一个状态对象时传递给构造函数的“裸”属性的状态对象。
当在将属性用作下一个对象构造函数的参数之前将转换应用于属性时,保留第一状态属性很容易(例如,使用 timeOfDay 很容易避免覆盖第一状态)。
我采用了“ map ”解决方法来避免在修改黑手党列表时引用第一状态对象,但这可能不是最干净或最容易理解的。
其他一些先前回答的问题建议使用类似 Object.assign({},this.mafia)
的内容,但这不允许在下面的代码中使用“pop 方法”。
请提出一种替代方案,以避免覆盖第一状态对象,如下所示。
class mafiaVillageState{
constructor(timeOfDay, villagers, mafia){
this.timeOfDay = timeOfDay;
this.villagers = villagers;
this.mafia = mafia;
}
killPlayer(){
let gameStep = new mafiaVillageState(1-this.timeOfDay,
this.villagers.map(v => {return v}),
// this.mafia
this.mafia.map(v => {return v})
// Object.assign({},this.mafia)
);
if (this.timeOfDay == 1){
gameStep.mafia.pop();
} else {
gameStep.villagers.pop();
}
return gameStep
}
}
let first = new mafiaVillageState(
1,
["Sana","Dahyun"], //the villagers
["Chaeyoung","Tzuyu"] //the mafia
)
“玩游戏”是通过获取下一个游戏状态来完成的:
let next = first.killPlayer();
console.log(first.timeOfDay);
console.log(first.mafia);
console.log(next.timeOfDay);
console.log(next.mafia);
- 输出没有任何解决方法,以避免引用第一个对象修改第一个状态(这不是期望的,因为我不想覆盖初始状态,以在选择要杀死的玩家要复杂得多时帮助调试)
1
Array(1) ["Chaeyoung"]
0
Array(1) ["Chaeyoung"]
- 使用“ map 解决方法”输出:这是所需的输出;一个黑手党被杀,第一个状态没有改变
1
Array(2) ["Chaeyoung", "Tzuyu"]
0
Array(1) ["Chaeyoung"]
-使用 Object.assign({},this.mafia)
会导致以下错误
' TypeError: gameStep.mafia.pop is not a function '
最佳答案
如果出于调试原因想要保留旧对象,则需要为新状态创建一个新对象,这是没有办法解决的。我不认为使用 .map 是一个糟糕的解决方案,但如果您正在寻找更干净的解决方案,您可以使用 es6 数组扩展运算符或 Array.prototype.splice。
killPlayer(){
let gameStep = new mafiaVillageState(
1 - this.timeOfDay,
[...this.villagers], // alternatively: this.villagers.splice(),
[...this.mafia],
);
...
}
展开运算符将数组中的项目转储到新数组中(您也可以执行 [...arr1, ...arr2] 等操作来组合数组)。您应该注意,这些项目不会被复制,因此如果您对任一数组中的某些内容进行变异,该变异将影响包含该对象的所有状态。
关于javascript - JS : new-state object created; prevent "pop" from affecting old-state object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57449759/