【问题标题】:Constant JSON object vales changing in the loop while creating a new object dynamically in javascript常量 JSON 对象值在循环中更改,同时在 javascript 中动态创建新对象
【发布时间】:2020-12-03 05:27:59
【问题描述】:

你好,我有一个模板对象如下:

const baseObj = {
  objKey: '',
  index: 1,
  cells: [
    {
      key: 'id',
      value: ''
    },
    {
      key: 'name',
      value: ''
    }
  ]
};

我想从数组中创建对象的动态数组,如下所示:

const allDetails = [
  {
    objKey: '876',
    name: 'abc',
    id: '123',
    address: '123abc'
  },
  {
    objKey: '098',
    name: 'def',
    id: '456',
    address: '456def'
  },
]

为此,我正在编写一个简单的循环,如下所示:

const allData = [];
for(let i = 0; i < allDetails.length; i++)
{
  const detail = allDetails[i];
  const row = Object.assign({}, baseObj);
  row.cells = Object.assign([], baseObj.cells);
  row.key = details.objKey;
  row.index = i+1;
  for(let j = 0; j < row.cells.length; j++)
  {
    const cell = row.cells[j];
    switch(cell.key){
      case 'id': {
        cell.value = detail.id;
        break;
      }
      case 'name': {
        cell.value = detail.name;
        break;
      }
    }
  }
  allData.push(row);
}

现在我期望 allData 是:

[
  {
    objKey: '876',
    index: 1,
    cells: [
      {
        key: 'id',
        value: '123'
      },
      {
        key: 'name',
        value: 'abc'
      }
    ]
  },
  {
    objKey: '098',
    index: 2,
    cells: [
      {
        key: 'id',
        value: '456'
      },
      {
        key: 'name',
        value: 'def'
      }
    ]
  }
]

但是当我打印时它给了我:

[
  {
    objKey: '876',
    index: 1,
    cells: [
      {
        key: 'id',
        value: '456'
      },
      {
        key: 'name',
        value: 'def'
      }
    ]
  },
  {
    objKey: '098',
    index: 2,
    cells: [
      {
        key: 'id',
        value: '456'
      },
      {
        key: 'name',
        value: 'def'
      }
    ]
  }
]

看起来数组值每次都被覆盖。在调试时,我可以在更改行单元格的值时以某种方式看到它也在更改 baseObj 的单元格的值。然而,只有对象数组出现了问题。我看不出哪里出错了,因为在每个循环中我都从 baseObj 创建了新的对象行。谁能发现我犯的错误。

【问题讨论】:

    标签: javascript arrays json ecmascript-6 javascript-objects


    【解决方案1】:

    你必须小心改变你的对象。最好深度克隆您的对象和数组。

    这是编写代码的另一种方式:

    const allData = [];
    for (let i = 0; i < allDetails.length; i++) {
        const detail = allDetails[i];
        const cells = [];
        for (let j = 0; j < baseObj.cells.length; j++) {
            const cell = {...baseObj.cells[j]};
            switch (cell.key) {
                case 'id':
                    cell.value = detail.id;
                    break;
                case 'name':
                    cell.value = detail.name;
                    break;
            }
            cells.push(cell)
        }
        const row = {objKey: detail.objKey, index: i + 1, cells};
        allData.push(row);
    }
    

    【讨论】:

      【解决方案2】:

      您的问题是:

      row.cells = Object.assign([], baseObj.cells);
      

      这会对数组进行浅拷贝,这意味着baseObj 内部的对象不会被复制,并且在每次迭代时都引用相同的对象引用。你可以通过克隆你的对象来解决这个问题,这可以通过使用来实现:

      row.cells = baseObj.cells.map(o => ({...o}));
      

      您还设置了row.key = detail.objKey,而这实际上应该是row.objectKey = detail.objKey

      请看下面的例子:

      const baseObj = {
        objKey: '',
        index: 1,
        cells: [{
            key: 'id',
            value: ''
          },
          {
            key: 'name',
            value: ''
          }
        ]
      };
      
      const allDetails = [{
          objKey: '876',
          name: 'abc',
          id: '123',
          address: '123abc'
        },
        {
          objKey: '098',
          name: 'def',
          id: '456',
          address: '456def'
        },
      ];
      
      const allData = [];
      for (let i = 0; i < allDetails.length; i++) {
        const detail = allDetails[i];
        const row = Object.assign({}, baseObj);
        row.cells = baseObj.cells.map(o => ({...o}));
        row.objKey = detail.objKey;
        row.index = i + 1;
        for (let j = 0; j < row.cells.length; j++) {
          const cell = row.cells[j];
          switch (cell.key) {
            case 'id':
              cell.value = detail.id;
              break;
            case 'name':
              cell.value = detail.name;
              break;
          }
        }
        allData.push(row);
      };
      
      console.log(allData);

      上述的另一种解决方案是使用.map() 构建一个新对象,我们从基础对象中获取/借用属性,并将任何重叠的属性替换为当前迭代对象中的属性:

      const baseObj = { objKey: '', index: 1, cells: [ { key: 'id', value: '' }, { key: 'name', value: '' } ] }; const allDetails = [ { objKey: '876', name: 'abc', id: '123', address: '123abc' }, { objKey: '098', name: 'def', id: '456', address: '456def' }, ];
      
      const result = allDetails.map(({objKey, address, ...r}, index) => ({
        ...baseObj, 
        objKey, 
        index: index+1, 
        cells: baseObj.cells.map(o => ({...o, value: r[o.key]}))
      }));
      
      console.log(result);

      【讨论】:

        猜你喜欢
        • 2014-11-06
        • 1970-01-01
        • 2016-02-22
        • 2017-07-24
        • 2011-01-23
        • 2012-07-23
        • 2020-02-12
        • 1970-01-01
        相关资源
        最近更新 更多