在下面的游戏代码中:即使使用了javascript new
关键字创建了一个新对象来保存下一个状态对象,应用于下一个状态对象的方法仍然引用了下一个状态对象制作下一个状态对象时,会将“裸”属性传递给构造函数。
在将变换用作属性作为下一个对象构造函数的参数之前,将其应用于属性时,保留第一状态属性很容易(例如,使用timeOfDay可以轻松避免覆盖第一状态)。
我已经采取了一种“地图”解决方法,以避免在修改黑手党列表时引用第一状态对象,但这可能不是最干净或最容易理解的。
其他一些先前回答的问题建议使用类似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"]
1
Array(2) ["Chaeyoung", "Tzuyu"]
0
Array(1) ["Chaeyoung"]
-使用Object.assign({},this.mafia)
会导致以下错误
' TypeError: gameStep.mafia.pop is not a function '
答案 0 :(得分:2)
如果出于调试原因要保留旧对象,则需要为新状态创建一个新对象,无法解决。我认为使用.map并不是一个糟糕的解决方案,但是如果您正在寻找更清洁的方法,则可以使用es6数组扩展运算符或Array.prototype.splice
。
killPlayer(){
let gameStep = new mafiaVillageState(
1 - this.timeOfDay,
[...this.villagers], // alternatively: this.villagers.splice(),
[...this.mafia],
);
...
}
spread运算符将要散布的数组中的项目转储到新数组中(您也可以执行[... arr1,... arr2]之类的操作来组合数组)。您应该注意,这些项目不会被复制,因此,如果您在任一阵列中进行某些突变,则该突变都会影响包含该对象的所有状态。