在 ES6 中使用跨页语法的深度复制

我正在尝试为我的 Redux 项目创建一个深度复制映射方法,该方法将用于对象而不是数组。我读到在Redux中,每个状态都不应该改变以前状态中的任何内容。

export const mapCopy = (object, callback) => {
    return Object.keys(object).reduce(function (output, key) {

        output[key] = callback.call(this, {...object[key]});

        return output;
      },
   {});
}

它的工作原理:

return mapCopy(state, e => {

    if (e.id === action.id) {
         e.title = 'new item';
    }

    return e;
})

但是,它不会深度复制内部项目,因此我需要将其调整为:

export const mapCopy = (object, callback) => {
    return Object.keys(object).reduce(function (output, key) {
     
    let newObject = {...object[key]};
    newObject.style = {...newObject.style};
    newObject.data = {...newObject.data};

    output[key] = callback.call(this, newObject);

    return output;
    }, {});
}

这不太优雅,因为它需要知道传递了哪些对象。在 ES6 中,有没有办法使用跨页语法来深度复制对象?


答案 1

使用 JSON 进行深度复制

var newObject = JSON.parse(JSON.stringify(oldObject))

var oldObject = {
  name: 'A',
  address: {
    street: 'Station Road',
    city: 'Pune'
  }
}
var newObject = JSON.parse(JSON.stringify(oldObject));

newObject.address.city = 'Delhi';
console.log('newObject');
console.log(newObject);
console.log('oldObject');
console.log(oldObject);

答案 2

ES6 中没有内置此类功能。我认为你有几个选择,这取决于你想做什么。

如果你真的想深度复制:

  1. 使用库。例如,lodash 有一个 cloneDeep 方法。
  2. 实现您自己的克隆功能。

针对特定问题的替代解决方案(无深度复制)

但是,我认为,如果你愿意改变一些事情,你可以为自己节省一些工作。我假设您控制函数的所有调用站点。

  1. 指定传递给 的所有回调都必须返回新对象,而不是改变现有对象。例如:mapCopy

    mapCopy(state, e => {
      if (e.id === action.id) {
        return Object.assign({}, e, {
          title: 'new item'
        });
      } else {  
        return e;
      }
    });
    

    这将使用 Object.assign 创建新对象,在该新对象上设置 的属性,然后在该新对象上设置新标题。这意味着您永远不会改变现有对象,而只会在必要时创建新对象。e

  2. mapCopy现在可以非常简单:

    export const mapCopy = (object, callback) => {
      return Object.keys(object).reduce(function (output, key) {
        output[key] = callback.call(this, object[key]);
        return output;
      }, {});
    }
    

从本质上讲,是信任其调用方做正确的事情。这就是为什么我说这假设你控制所有呼叫站点。mapCopy