Javascript - 如何更改一个列表而不修改另一个列表

时间:2018-02-19 21:54:37

标签: javascript arrays

我有以下代码:

const heroes = [
  { name: 'Wolverine',      family: 'Marvel',    isEvil: false },
  { name: 'Deadpool',       family: 'Marvel',    isEvil: false },
  { name: 'Magneto',        family: 'Marvel',    isEvil: true  },
  { name: 'Charles Xavier', family: 'Marvel',    isEvil: false },
  { name: 'Batman',         family: 'DC Comics', isEvil: false },
  { name: 'Harley Quinn',   family: 'DC Comics', isEvil: true  },
  { name: 'Legolas',        family: 'Tolkien',   isEvil: false },
  { name: 'Gandalf',        family: 'Tolkien',   isEvil: false },
  { name: 'Saruman',        family: 'Tolkien',   isEvil: true  }
]

var newHeroes = heroes.slice(0);

newHeroes[0] = { name: 'Test', family: '2', isEvil: false };
newHeroes[1].name = 'Test 2';

console.log(newHeroes);
console.log(heroes);

当我切片第一个数组时,我预计第二个数组是英雄const的非内存副本。所以,每当我更改newHeroes数组时,我认为第一个不会改变。

当我更改整个内容(如newHeroes [0] = Object)时,它完美无缺。这只会改变第二个数组。

但是当我尝试直接更改属性时(newHeroes [1] .name ='Test 2'),它在两个数组中都会发生变化。

有人能解释我为什么吗?

谢谢! : - )

1 个答案:

答案 0 :(得分:1)

您需要创建数组的深层副本,因为您的数组由对象组成,而对象又拥有自己的引用。切片只会创建一个浅拷贝。你可以这样做:

const heroes = [
  { name: 'Wolverine',      family: 'Marvel',    isEvil: false },
  { name: 'Deadpool',       family: 'Marvel',    isEvil: false },
  { name: 'Magneto',        family: 'Marvel',    isEvil: true  },
  { name: 'Charles Xavier', family: 'Marvel',    isEvil: false },
  { name: 'Batman',         family: 'DC Comics', isEvil: false },
  { name: 'Harley Quinn',   family: 'DC Comics', isEvil: true  },
  { name: 'Legolas',        family: 'Tolkien',   isEvil: false },
  { name: 'Gandalf',        family: 'Tolkien',   isEvil: false },
  { name: 'Saruman',        family: 'Tolkien',   isEvil: true  }
]

var newHeroes = heroes.reduce((newArr, hero) => {
  newArr.push({...hero}); // creating a shallow copy of this object
  return newArr;
}, [])

newHeroes[0] = { name: 'Test', family: '2', isEvil: false };
newHeroes[1].name = 'Test 2';

console.log(newHeroes);
console.log(heroes);