在 Javascript 中,如何告诉 array.filter() 复制新数组中的元素对象?



所以简化了代码。

var a = [
{ name: "first", num: 1 },
{ name: "first", num: 2 },
{ name: "first", num: 3 },
{ name: "first", num: 4 },
{ name: "first", num: 5 },
{ name: "first", num: 6 },
{ name: "first", num: 7 },
{ name: "first", num: 8 },
{ name: "first", num: 9 }
];
var b = a.filter(function(el) {
return el.num % 2 == 0;
});
console.log("a1", a); // [1, 20, 3, 40, 5, 60, 7, 80, 9]
console.log("b1", b); // [20, 40, 60, 80]
for (let i = 0; i < b.length; i++) {
b[i].num = b[i].num * 10;
}
console.log("a2", a); // [1, 20, 3, 40, 5, 60, 7, 80, 9]
console.log("b2", b); // [20, 40, 60, 80]

我的新理解是数组元素包含对对象的引用,而不是对象。 有哪些方法可以复制这些对象?

过滤
  1. ,然后从过滤的数组中构建新对象并将新事物放入新数组中?
  2. 使用一些我目前不熟悉的方法?
  3. 重新设计代码以停止使用数组中的对象?

另外,console.log(( 显示变量在放置在 for 循环之前时发生了变化是怎么回事?

如果你想复制数组中的对象,你应该使用map函数。

var b = a.filter(val => val.num %2 === 0).map(val => Object.assign({}, val, { num: val.num * 10}));

map 函数将返回一个新数组,其中包含从函数返回的值。 在此示例中,我们将创建一个新对象Object.assign({})并在更改num字段时复制现有对象。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

如果你想克隆对象,你需要一个克隆函数,我用这个函数

const clone = obj =>
Array.isArray(obj)
? obj.map(item => clone(item))
: obj instanceof Date
? new Date(obj.getTime())
: obj && typeof obj === 'object'
? Object.getOwnPropertyNames(obj).reduce((o, prop) => {
o[prop] = clone(obj[prop]);
return o;
}, {})
: obj;

然后,您可以使用

let c = clone(b);

这将是一个新数组,其中每个对象都是一个新的克隆。

var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3}, 
{name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7}, 
{name:'first', num: 8}, {name:'first', num: 9}];
var b = a.filter(function(el){return el.num%2==0 });

const clone = obj =>
Array.isArray(obj)
? obj.map(item => clone(item))
: obj instanceof Date
? new Date(obj.getTime())
: obj && typeof obj === 'object'
? Object.getOwnPropertyNames(obj).reduce((o, prop) => {
o[prop] = clone(obj[prop]);
return o;
}, {})
: obj;
let c = clone(b);

console.log(b[0] === c[0]);

是的,数组a的元素都是指针。 所以你需要使用Object.assign(正如许多人所说(

和其他带有阵列的解决方案减少了使用量(请参阅阿德里安·布兰德评论(

var a = [ { name: 'first', num: 1 } 
, { name: 'first', num: 2 } 
, { name: 'first', num: 3 } 
, { name: 'first', num: 4 } 
, { name: 'first', num: 5 } 
, { name: 'first', num: 6 } 
, { name: 'first', num: 7 } 
, { name: 'first', num: 8 } 
, { name: 'first', num: 9 } 
] 
var b = a.filter(el=>!(el.num%2)).map(el=>Object.assign({},el))
// other solution with reduce 
var c = a.reduce((acc,cur)=>{
if (!(cur.num%2) )acc.push(Object.assign({},cur))
return acc
}, [])
ConsoleArrayNamNum('var a -1-',a)  // [1,2,3,4,5,6,7,8,9]
ConsoleArrayNamNum('var b -1-',b)  // [2, 4, 6, 8]
ConsoleArrayNamNum('var c -1-',c)  // [2, 4, 6, 8]
for(let elm of b)
{ elm.num *= 10 }
ConsoleArrayNamNum('var a -2-',a)  // [1,2,3,4,5,6,7,8,9]
ConsoleArrayNamNum('var b -2-',b)  // [20, 40, 60, 80]
function ConsoleArrayNamNum(title,arr) {
console.log(title)
for(let elm of arr)
{ console.log(`{ name: '${elm.name}', num: ${elm.num} }`) }
}
.as-console-wrapper { min-height: 100% !important; }

如果你想要一个带有最终值的新数组,你可以使用 reduce 一次性完成所有操作,reduce从一个空数组的累加器开始,如果它满足条件,每次迭代都会添加一个克隆,展开运算符覆盖 num time 10。

var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3}, 
{name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7}, 
{name:'first', num: 8}, {name:'first', num: 9}];
const evensTimes10 = array => array.reduce((results, item) => {
if (item.num % 2 === 0) {
results.push({ ...item, num: item.num * 10 });
}
return results;
}, []);
var b = evensTimes10(a);
console.log('a1',a); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log('b1',b); // [20, 40, 60, 80]

使用一些 ES6 语法的简单解决方案:

var a = [{name: 'first', num:1}, {name:'first', num: 2}, {name:'first', num: 3}, 
{name:'first', num: 4}, {name:'first', num: 5}, {name:'first', num: 6}, {name:'first', num: 7}, 
{name:'first', num: 8}, {name:'first', num: 9}];
const b = a
.filter(el => {
if (el.num % 2 === 0) {
return {
...el
}
}
})
.map(newEl => newEl.num * 10);
console.log('a', a);  // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log('b', b);

  1. .filter(( 迭代 "a" 数组并仅返回具有 满足条件的"num"属性。这是一个克隆阵列。
  2. return { ...el }返回一个克隆的对象,这要归功于传播 算子。
  3. .map(( 创建一个新数组并返回每个 "el.num" 值 * 10

这里有一些关于 .map(( .filter(( 和 spread 运算符的信息:

  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

我发现了这个非常有趣的网站,它列出了所有Javascript函数及其描述,并显示了是否可变,这很有帮助: https://doesitmutate.xyz/

最新更新