使用for-of更新数组对象

时间:2018-08-31 06:51:44

标签: javascript arrays for-loop

我有以下两个对象数组。我想做的是,如果id属性匹配,则将数组x项替换为数组y项。

我可以从一个普通的 for 循环轻松实现这一目标。但我不明白为什么我的 for 循环返回不同的结果。

let x1 = [{
  id: '1',
  a: 1,
  b: 2
}];

let y1 = [{
  id: '1',
  c: 3,
  b: 2
}];

let x2 = [{
  id: '1',
  a: 1,
  b: 2
}];

let y2 = [{
  id: '1',
  c: 3,
  b: 2
}];



let updateX1 = (x, y) => {

  for (let itemY of y) {

    for (let itemX of x) {

      if (itemY.id === itemX.id) {
        itemX = itemY;
      }
    }
  }

  return x;
}

let updateX2 = (x, y) => {

  for (let i = 0; i < y.length; i++) {

    for (let j = 0; j < x.length; j++) {

      if (y[i].id === x[j].id) {
        x[j] = y[i];
      }
    }
  }

  return x;
}

console.log(updateX1(x1, y1));
console.log(updateX2(x2, y2));

为什么上述两种方法会得到两种不同的结果?预先感谢!

2 个答案:

答案 0 :(得分:5)

本身重新分配变量将永远不会使现有对象发生变异,或者至少不会在非常奇怪的情况下进行变异。当你做

itemX = itemY;

您只是将itemX变量指向的值更改为itemY。最初的itemX以及itemX所来自的对象都不会更改。为了使对象变异,您必须始终明确地为对象的 property 分配一个新值,例如使用obj.fooobj['foo']或在代码中, x[j] = y[i];

答案 1 :(得分:1)

如果您实际上想说的是:

  

如果id属性匹配,则将数组x项替换为数组y   项目

然后可以将mapfind结合使用,而不是嵌套循环:

const x = [
  { id: 1, name: 'should be replaced by y' },
  { id: 2, name: 'not replaced' },
];
const y = [
  { id: 1, name: 'this is from y' },
  { id: 3, name: 'not not used' },
];

const newX = x.map((xItem) => {
  const fromY = y.find((yItem) => yItem.id === xItem.id);
  return fromY ? fromY : xItem;
});
console.log(newX);

如果要进行突变,则可以使用forEach,因为它更适合副作用

const x = [
  { id: 1, name: 'should be replaced by y' },
  { id: 2, name: 'not replaced' },
];
const y = [
  { id: 1, name: 'this is from y' },
  { id: 3, name: 'not not used' },
];
//mutate x
x.forEach((xItem, index) => {
  const fromY = y.find((yItem) => yItem.id === xItem.id);
  x[index] = fromY ? fromY : xItem;
});
console.log(x);