代码之家  ›  专栏  ›  技术社区  ›  d-_-b

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

  •  2
  • d-_-b  · 技术社区  · 6 年前

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

    有没有办法 map filter 不修改原稿?我可以考虑遍历每一个项目并创建一个克隆,但我很好奇是否有更简单的方法。

    4 回复  |  直到 6 年前
        1
  •  3
  •   Olian04    6 年前

    这不是问题 map filter ,这些方法总是返回一个新数组。在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

    如果要在执行映射时创建数组中每个对象的副本,可以使用spread运算符:

    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

    值得注意的是,spread操作符是一个浅层克隆,这意味着对象中的对象仍将通过引用传递。

    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
  •  4
  •   Mark    6 年前

    除了 password 与解引用。然后使用map构建一个包含其他内容的新对象。如果对象上有其他属性而不是 name 想要包括所有的东西除了 密码 .

    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
        3
  •  1
  •   Dan    6 年前

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

    const objectsWithNames = objects.map(({name}) => ({name}));
    
        4
  •  0
  •   clabe45    6 年前

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

    所以,正如您所说,您可以循环遍历每个项并创建一个克隆。当然,您也可以执行整个数组的深度复制。