0

I have a javascript object that maintains an internal array of objects. I have a method that returns the array but I need to prevent external manipulation of the array and the objects inside it.

Trying slice to copy the array but I've noticed that the objects inside are still references to the originals while the array itself is new. I've never noticed this before, but I've confirmed it:

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/

I need to have a truly new copy so an outsider can't modify the array without using the API methods I've designed. I assume all I can do iterate the array and use $.extend (or similar methods from other libs) to clone the objects individually - is there any easier/native alternative?

helion3
  • 34,737
  • 15
  • 57
  • 100
  • Interesting performance test: http://jsperf.com/cloning-an-object/6... – War10ck Dec 04 '14 at 21:28
  • None of the comments/answers are addressing the fact that these are objects in array. I don't want to individually clone every object and build a new array, but it seems that all I can do. – helion3 Dec 04 '14 at 21:36
  • The first nor the second question on the duplicate answer referenced an array of objects?... – War10ck Dec 04 '14 at 21:38

1 Answers1

1

A simple implementation of a deep copy is

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

Note that this won't work if you have cyclical references in your object, or if you have functions.

You can also use jQuery.extend passing true as the first argument for a deep copy

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>
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • Note that there is also an issue with date conversion. See [this comment](http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-an-object#comment-39444922). – War10ck Dec 04 '14 at 21:36