Arrays vuex中状态的生成和变异

Arrays vuex中状态的生成和变异,arrays,vue.js,vuejs2,vuex,Arrays,Vue.js,Vuejs2,Vuex,我使用Array()构造函数创建一个大小为3的空数组,然后使用forEach()或Array.fill()填充它,但当我尝试更改/变异数组中的任何元素时,另一个数组中任何类似成员的值都会设置为分配给任何其他成员的最后一个值。 创作方法: const createBoard = () => { let row = Array(3); const cellDS = { isClcicked: false, toPlayer: null, cellID: null

我使用Array()构造函数创建一个大小为3的空数组,然后使用forEach()或Array.fill()填充它,但当我尝试更改/变异数组中的任何元素时,另一个数组中任何类似成员的值都会设置为分配给任何其他成员的最后一个值。 创作方法:

const createBoard = () => {
  let row = Array(3);
  const cellDS = {
    isClcicked: false,
    toPlayer: null,
    cellID: null,
  };
  row.fill(cellDS);
  let gameBoard = Array(3);
  gameBoard.fill(row);
  console.log("board created");
  return gameBoard;
};
当我更改第一行的第一个元素的单元格ID时,我得到以下结果:

[[
  { isClicked: false, toPlayer: null, cellID: 1 },
  { isClicked: false, toPlayer: null, cellID: 1 },
  { isClicked: false, toPlayer: null, cellID: 1 },
],
[
  { isClicked: false, toPlayer: null, cellID: 1 },
  { isClicked: false, toPlayer: null, cellID: 1 },
  { isClicked: false, toPlayer: null, cellID: 1 },
],
[
  { isClicked: false, toPlayer: null, cellID: 1 },
  { isClicked: false, toPlayer: null, cellID: 1 },
  { isClicked: false, toPlayer: null, cellID: 1 },
]]
同样适用于isClicked和toPlayer

Vuex代码:

const state = { gameBoard: [] };
const getters = {
  getGameBoard: (state) => state.gameBoard,
};
const actions = {
  createBoard: ({ commit }) => {
    commit("setBoard");
  },
  editBoard: ({ commit }) => {
    commit("changeBoard");
  },
};
const mutations = {
  setBoard: (state) => {
    state.gameBoard = createBoard();
  },
  changeBoard: (state) => {
    console.log("Before: " + state.gameBoard[0][0]["cellID"]);
    state.gameBoard[0][0]["cellID"] = 1;
    console.log("After: " + state.gameBoard[0][0]["cellID"]);
    console.log("After: " + state.gameBoard[0][1]["cellID"]);
  },
}

解决方案:
fill()在整个应用程序中创建元素的精确静态副本,并且不能简单地在空数组上使用forEach,例如数组(3)将返回[,],这本身是没有意义的(未定义的)。
因此,您可以将其填充为null,然后对其使用forEach()。

您需要了解JS中的对象以及值类型和对象类型之间的差异。在您的例子中,
fill
方法仅使用相同的对象填充数组,如果更改此对象的某些字段,则会更改数组的所有条目,因为这是完全相同的对象。此数组仅存储对此对象的引用,而不存储其副本

如果希望创建此对象的独立副本,则应在
for
循环中创建它们,以通过对象的自身副本填充数组的每个元素

for (let ind=0; ind< row.length; ind++) {
  row[ind] = Object.assign({}, cellDS); 
}
for(让ind=0;ind
请记住,使用
Object.assign
您不会复制所有内部对象道具,而只复制值类型道具。对象类型道具将指向与原始对象中相同的对象。
要制作对象的深度副本,您应该使用
lodash
包中的
cloneDeep
函数。

我尝试使用您的代码片段,但它从数组返回了相同的空数组(3)到目前为止有效的方法是使用null填充它们,然后使用forEach生成所需的数组行。fill(null);row.forEach((x,y)=>{row[y]=Object.assign({},cellDS);console.log(x,y,cellDS);});很抱歉,
forEach
不考虑数组的空元素。您应该为
使用一个简单的
。请参阅更新的答案用空数组填充空数组同样有效如果您可以用它更新答案如果您希望将数组的长度作为参数传递,那么您应该使用我的解决方案,因为您可以指示空数组的动态数量您不能简单地在[,]上使用forEach