简体   繁体   English

Javascript Array.map复制而不更改原始版本

[英]Javascript Array.map copy without changing original

I've noticed that deleting object properties when using Array.map() affects the original array, I assume since each iteration's item is still referencing the original array: 我注意到在使用Array.map()时删除对象属性会影响原始数组,我假设因为每个迭代的项仍然引用原始数组:

var objects = [{name: 'a', password: 'x'}, {name: 'b', password: 'x'}];

var clean = objects.map(user => {delete user.password; return user;});

console.log(JSON.stringify(objects));
> [{"name":"a"},{"name":"b"}]

Is there a way to use map or filter without it modifying the original? 有没有办法使用mapfilter而不修改原件? I can think to loop through each item and create a clone but curious if there's a simpler way. 我可以考虑循环每个项目并创建一个克隆但是好奇,如果有一个更简单的方法。

You can reference everything except password with dereferencing. 您可以通过解除引用来引用password以外的所有内容。 Then use map to build a new object with everything else. 然后使用map用其他所有东西构建一个新对象。 This is nice if you have other properties on the object other than name and want to include everything except password . 如果除了name之外的对象上有其他属性并希望包含除password之外的所有内容,那么这很好。

 var objects = [{name: 'a', password: 'x'}, {name: 'b', password: 'x'}]; var clean = objects.map(({password, ...user}) => user); console.log(objects); // untouched console.log(clean); // no password 

This is not a problem with map or filter , these methods always return a new array. 这不是mapfilter的问题,这些方法总是返回一个新数组。 This is a problem with objects always being passed by reference in Javascript. 这是在Javascript中始终通过引用传递的对象的问题。

Consider the following: 考虑以下:

 const a = { foo: 1 } const b = { foo: 2 } const arr1 = [ a, b ]; const arr2 = arr1.map(v => { v.foo = 0; return v; }); console.log(arr1); console.log(arr2); console.log(JSON.stringify(arr1) === JSON.stringify(arr2)) // true 

If you want to create a copy of each object in an array while doing a map you could use the spread operator: 如果要在执行映射时创建数组中每个对象的副本,可以使用扩展运算符:

 const a = { foo: 1 } const b = { foo: 2 } const arr1 = [ a, b ]; const arr2 = arr1.map(v => { return {...v, foo: 0}; }); console.log(arr1); console.log(arr2); console.log(JSON.stringify(arr1) === JSON.stringify(arr2)) // false 

It's worth noting that the spread operator is a shallow clone, this means that objects within objects will still be passed by reference. 值得注意的是,扩展运算符是浅层克隆,这意味着对象中的对象仍将通过引用传递。

 const c = { foo: 3 } const a = { foo: 1, biz: c } const b = { foo: 2, biz: c } const arr1 = [ a, b, c ]; const arr2 = arr1.map(v => { return {...v, foo: 0}; }); console.log(arr1); console.log(arr2); console.log(JSON.stringify(arr1) === JSON.stringify(arr2)) // false 

您可以映射所有项目并仅返回名称。

const objectsWithNames = objects.map(({name}) => ({name}));

The original array isn't being modified, but rather the items in the array (the objects) are. 原始数组未被修改,而是数组中的项(对象)。 Since javascript objects are passed by reference, when you modify the objects in the new array, the references in the old array show the same modifications. 由于javascript对象是通过引用传递的,因此当您修改新数组中的对象时,旧数组中的引用显示相同的修改。

So, as you said, you can loop through each item and create a clone. 所以,正如你所说,你可以遍历每个项目并创建一个克隆。 Of course, you could perform a deep copy of the entire array too. 当然,您也可以执行整个阵列的深层复制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM