2014-12-04 200 views
0

我有一个维护内部对象数组的javascript对象。我有一个方法返回数组,但我需要防止数组和它内部的对象的外部操纵。对象的深度克隆

尝试slice来复制数组,但我注意到里面的对象仍然是引用而原始数组本身是新的。我以前从来没有注意到这一点,但我已经证实了它:

function test(){ 

    // I want this to be safe from outside influence 
    var a = [{ 
     val: 1 
    },{ 
     val: 2 
    }]; 

    return { 
     all: function(){ 
      return a.slice(); 
     } 
    } 
} 

var instance = test(); 
var copy = instance.all(); 

// This affects both "copy" and the original 
copy[0].val = 'wrong'; 

// This clears "copy" but doesn't affect the original 
copy = []; 

http://jsfiddle.net/dczz7sL4/1/

我需要有一个真正的新副本,以便外人无法不使用API​​方法我修改数组已经设计好了。我假设我可以迭代数组并使用$.extend(或来自其他库的类似方法)来单独克隆对象 - 是否有更简单/本机的替代方案?

+0

有趣的性能测试:http://jsperf.com/cloning-an-object/6 ... – War10ck 2014-12-04 21:28:35

+0

没有任何评论/答案正在解决这些是数组中的对象这一事实。我不想单独克隆每个对象并构建一个新的数组,但似乎只有我能做到。 – helion3 2014-12-04 21:36:54

+0

关于重复答案的第一个问题和第二个问题引用了一个对象数组? – War10ck 2014-12-04 21:38:28

回答

1

的简单实现的深层副本是

function clone(obj) { 
    return JSON.parse(JSON.stringify(obj)); 
} 

请注意,这不会,如果你在你的对象有循环引用,如果您有职能的工作,或。

您还可以使用jQuery.extend传递true作为第一个参数的深副本

var a =[{a:1}] 
 
var b = $.extend(true, [], a); 
 
b[0].a = 0; 
 
$('#first').html(JSON.stringify(a)); 
 
$('#second').html(JSON.stringify(b));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
First Array: <span id='first'></span> <br /> 
 
Clonde Array: <span id='second'></span>

+0

请注意,日期转换也存在问题。看[这个评论](http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-an-object#comment-39444922)。 – War10ck 2014-12-04 21:36:24