2016-02-05 38 views
0

我有几个JS对象。他们可以有任何结构:制作一个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_idfirst._ref_id()每当我tryi ng来访问它的值。

但我不知道如何重置记忆变量从应对函数内,或者如果这甚至是可能的?

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

PS:

我使用lodash和immutable.js在这个项目,但我还没有找到这个特殊任务的任何辅助功能。

+0

我不熟悉,记忆化,但我看不出它如何帮助解决你的问题。我会采取深层复制方法,在此期间我会寻找“瞬态场”来重新实现它,而不是复制它。 – Aaron

+0

memoization只是当我** first._ref_id()**重复同一个对象,我总是会得到相同的结果。但如果以某种方式,我将'注入'/更改memoized变量的值之间的新值将被生成的调用。但我的思维方式可能完全错误。你能否提供你的解决方案的例子? – Kocur4d

+0

当然,在它上面工作 – Aaron

回答

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 
+0

很酷,对于我运行的所有示例而言,它们都非常合适。我会等待几天,接受它作为答案,我只是非常感兴趣,看看它是否可以用不同的方法完成。我会在周末做更多的研究。非常感谢你的队友。 – Kocur4d

+0

不客气! JS中通过使用JSON.parse/JSON.stringify至少还有另一种方法来深入复制对象,其中JSON.parse方便地接受一个回调方法,该方法将授予它更改_ref_id字段值的可能性。代码将更加简洁,但我读过它的效率也低得多。 – Aaron

+0

@Aaron恕我直言,使用序列化来复制对象是可怕的。我也看到它也用在HTML上,但它不对! – Alnitak

相关问题