为什么array.map不返回新数组?

时间:2019-04-04 09:28:30

标签: javascript arrays ecmascript-6

我想使用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

1 个答案:

答案 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);