我想使用map函数创建数组的副本,但是我得到了相同的引用。我不明白为什么。 我想有另一种方法来创建数组的副本。
我使用map函数创建了原始数组的副本,然后在副本上使用了filter函数来变异单个元素。我希望原始数组不会被突变,但是实际上是。
有人可以给我背景信息为什么会发生这种情况以及正确复制数组,创建对另一个对象的引用的正确方法吗?
const arr = [{name: 'hello'}, {name: 'world'}]
const arr2 = arr.map(i => i)
const [partial] = arr2.filter(i => i.name === 'hello')
partial.name = 'HELLO'
arr2[0].name === 'HELLO' // true
arr[0].name === 'HELLO' // true
答案 0 :(得分:3)
对象和数组是JavaScript中的引用类型,这意味着在复制它们时,您正在复制它们的引用,该引用仍指向原始对象。
因此,当您使用:
const arr2 = arr.map(i => i);
您正在将项目从arr
逐一复制到arr2
。并且由于这些项目是对象,因此仅复制其引用。您确实有两个不同的数组,但是它们包含对相同对象的引用。
相反,您可以在映射时使用传播运算符对内部对象进行浅表复制:
const arr = [{name: 'hello'}, {name: 'world'}]
const arr2 = arr.map(o => ({ ...o })) // spread operator + implicit return notation
arr[0].name = 'bye';
console.log(arr[0].name, arr2[0].name);
如评论中@ 3limin4t0r 所述,您也可以使用Object.assign({}, o)
而不是{ ...o }
进行浅表复制,因为属性的散布运算符当前位于ECMAScript proposal stage 4:
const arr = [{name: 'hello'}, {name: 'world'}]
const arr2 = arr.map(o => Object.assign({}, o))
arr[0].name = 'bye';
console.log(arr[0].name, arr2[0].name);