我对map()的行为感到很困惑。
我有一个像这样的对象数组:
const products = [{
...,
'productType' = 'premium',
...
}, ...]
我正在将这个数组传递给一个函数,该函数应返回相同的数组,但所有产品都是免费的:
[{
...,
'productType' = 'free',
...
}, ...]
功能是:
const freeProduct = function(products){
return products.map(x => x.productType = "free")
}
返回以下数组:
["free", "free", ...]
所以我把我的功能重写为:
const freeProduct = function(products){
return products.map(x => {x.productType = "free"; return x})
}
按预期返回数组。
但是!那是我放松心情的时刻,在这两种情况下我的原始产品阵列都被修改了。
map()周围的文档说它不应该(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)。
我甚至试图创建一个我的数组的克隆来转换我的函数
const freeProduct = function(products){
p = products.splice()
return p.map(x => {x.productType = "free"; return x})
}
但我仍然得到相同的结果(这开始让我发疯)。
我会非常感谢任何可以解释我做错事的人!
谢谢
答案 0 :(得分:57)
您没有修改原始阵列。您正在修改数组中的对象。如果您想避免改变数组中的对象,可以使用Object.assign
创建一个具有原始属性的新对象以及您需要的任何更改:
const freeProduct = function(products) {
return products.map(x => {
return Object.assign({}, x, {
productType: "free"
});
});
};
2018编辑:
在most browsers中,您现在可以使用对象扩展语法而不是Object.assign
来完成此操作:
const freeProduct = function(products) {
return products.map(x => {
return {
...x,
productType: "free"
};
});
};
答案 1 :(得分:12)
详细说明SimpleJ的答案 - 如果你是= =两个数组,你会发现它们不相等(内存中的地址不同),确认映射的数组实际上是一个新的数组。问题是你正在返回一个新数组,它充满了对原始数组中SAME对象的引用(它没有返回新的对象文字,它返回对同一对象的引用)。因此,您需要创建作为旧对象副本的新对象 - 即,使用SimpleJ给出的Object.assign示例。
答案 2 :(得分:1)
不幸的是,无论散布运算符还是对象赋值运算符都进行深层复制。...您需要使用类似lodash的函数来获得面拷贝,而不仅仅是参考拷贝。
0, 1, 5, 6
答案 3 :(得分:0)
Array迭代器Array.map()创建具有相同数量元素的新数组,或者不更改原始数组。如果数组内部复制了相同的引用,则引用可能存在问题,因此,当您对对象的属性进行任何更改时,它将更改具有相同引用的元素的原始值。
解决方案是复制对象,在这种情况下,array.Splice()
和[...array]
(扩展运算符)无济于事,您可以使用Loadash之类的JavaScript Utility库,也可以只使用使用以下提及代码:
const newList = JSON.parse(JSON.stringify(orinalArr))