制作JS对象的副本以改变给定键的出现

时间:2016-02-05 14:29:28

标签: javascript

我有很少的JS对象。他们可以有任何结构:

{
  name: "first",
  _ref_id: 1234,
  spec: {
    _ref_id: 2345,
    data: "lots of data"
  }
}

{
  name: 'second',
  _ref_id: 5678,
  container: {
    _ref_id: 6789,
    children: [
      {_ref_id: 3214, name: 'Bob'}
      {_ref_id: 1111, name: 'Mark'}
      {_ref_id: 2222, name: 'Frank'}
    ]
  }
}

问题:

我需要制作此对象的副本,但使用不同的_ref_ids。

创建'第一个'对象,我的样子如下:

first = {
  name: "first",
  _ref_id: uuid.v4(),
  spec: {
    _ref_id: uuid.v4(),
    data: "lots of data"
  }
}

所以当我创建对象的时候我知道了对象的结构,但是在我想要复制这个对象的地方进一步向下链接我没有访问权限我不知道是什么我拥有的这个对象的结构就是它自己的对象。因此,在应对“第一次”后,我希望:

{
  name: "first",
  _ref_id: 8888,
  spec: {
    _ref_id: 9999,
    data: "lots of data"
  }
} 

我尝试在对象创建过程中将_ref_id定义为一个简单的值,而不是将其定义为一种memoized函数:

refId(memoized = true){
  var memo = {}
  return () => {
    if(!memoized) memo = {}
    if(memo['_ref_id'])
      return memo._ref_id
    else {
      memo._ref_id = uuid.v4()
      return memo._ref_id
    }
  }
}

所以我可以创建它:

first = {
  name: "first",
  _ref_id: refId(),
  spec: {
    _ref_id: refId(),
    data: "lots of data"
  }
}

每当我尝试访问它的值时,将 first._ref_id 更改为 first._ref_id()

但是我不知道如何从复制功能中重置 memoized 变量,或者甚至可以这样做?

有没有人有类似的问题?也许有不同的解决方法?

PS:

我在这个项目中使用了lodash和immutable.js但是我还没有找到任何帮助这个特定任务的函数。

1 个答案:

答案 0 :(得分:1)

Most elegant way to clone a JS object启发,检查_ref_id字段:

function deepCopyWithNewRefId(obj) {
    if (null == obj || "object" != typeof obj) return obj;
        var copy = obj.constructor();
        for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) {
            if (attr == "_ref_id") {
                copy[attr] = uuid.v4();
            } else {
                copy[attr] = deepCopyWithNewRefId(obj[attr]);
            }
        }
    }
    return copy;
}

使用日志:

var uuid = { v4 : function(){ return Math.random()} };
var first = {
  name: "first",
  _ref_id: uuid.v4(),
  spec: {
    _ref_id: uuid.v4(),
    data: "lots of data"
  }
};
console.log(first._ref_id);
console.log(first.spec._ref_id);
var second = deepCopyWithNewRefId(first);
console.log(second);
console.log(second._ref_id);
console.log(second.spec._ref_id);
// the printed values are not the same. The rest of the object is