Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clone an array in javascript without using JSON.stringify or JSON.parse? [duplicate]

I have an array example fruit . I'd like to copy it as array fruits2, without keeping reference.

As in the following example reference is kept so fruits is modified.


var fruit = function (name){
    this.name = name;
}
var fruits = [];
fruits.push(new fruit('apple'));
fruits.push(new fruit('banana'));
fruits.push(new fruit('orange'));

var fruits2 = fruits;
fruits2.length = 0;
console.log(fruits);

http://jsfiddle.net/vkdqur82/


Using JSON.stringify and JSON.parse does the trick but the objects in fruits2 are not any longer of type fruit but are of general type object

var temp = JSON.stringify(fruits);
var fruits2 = JSON.parse(temp);

I would like to know an alternative approach which would keep inner object of fruit.

like image 232
GibboK Avatar asked Sep 11 '14 19:09

GibboK


2 Answers

Use slice: var fruits2 = fruits.slice(); should do it.

Your jsFiddle, modified

See also: MDN

**Edit. I was a bit lazy, let's correct my answer to make up for that.

For an Array of just values slice is perfect. For an Array of objects or arrays or a mix of values/objects/arrays, the Array and Object elements of the Array to clone need cloning too. Otherwise they will be references to the original arrays or objects (so: not copies) and a change of one [of these references of arrays or objects] will be reflected in all 'clones' containing a reference to it.

To clone an Array of Arrays/Objects/mixed values Array.map is your friend. There are several methods to think of:

  1. creating a new instance with old data
    var fruits1 = fruits.map(function(v) {return new Fruit(v.name);});
  2. using JSON
    var fruits2 = fruits.map(function(v) {return JSON.parse(JSON.stringify(v));});
  3. create and use some cloning method
    var fruits3 = fruits.map(function(v) {return cloneObj(v);});

In case 3, a method for cloning could look like:

function cloneObj(obj) {
    function clone(o, curr) {
        for (var l in o){
            if (o[l] instanceof Object) {
                curr[l] = cloneObj(o[l]);
            } else {
                curr[l] = o[l];
            }
        }
        return curr;
    }
    
    return obj instanceof Array 
             ? obj.slice().map( function (v) { return cloneObj(v); } )
             : obj instanceof Object 
               ? clone(obj, {})
               : obj;
}

Using this cloneObj method, Array.map is obsolete.
You can also use var fruitsx = cloneObj(fruits);

The jsFiddle from the link above is modified to demonstrate these methods.

For Array.map, see again MDN

like image 108
KooiInc Avatar answered Oct 06 '22 00:10

KooiInc


slice can do the trick.

You can also use .map but .slice is normally faster.

var copy = fruits.map(function(item) {return item});

Hope it helps

like image 21
php-dev Avatar answered Oct 05 '22 22:10

php-dev