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

时间:2018-08-03 15:21:26

标签: javascript

我注意到使用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"}]

是否可以使用mapfilter而不修改原始文件?我可以考虑遍历每个项目并创建一个克隆,但很好奇是否有更简单的方法。

4 个答案:

答案 0 :(得分:4)

您可以通过引用取消引用password以外的所有内容。然后使用map与其他所有内容一起构建新对象。如果您在对象上具有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

答案 1 :(得分:3)

mapfilter都不是问题,这些方法总是返回一个新数组。这是对象始终通过Javascript引用传递的问题。

请考虑以下内容:

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

如果要在制作地图时在数组中创建每个对象的副本,则可以使用散布运算符:

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

值得注意的是,散布运算符是一个浅表克隆,这意味着对象内的对象仍将通过引用传递。

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

原始数组没有被修改,而是数组中的项目(对象)被修改了。由于javascript对象是通过引用传递的,因此当您修改新数组中的对象时,旧数组中的引用会显示相同的修改。

因此,正如您所说,您可以遍历每个项目并创建一个克隆。当然,您也可以对整个数组进行深层复制。