Rose Perrone
Rose Perrone

Reputation: 63556

jquery.extend(true, [], obj) not creating a deep copy

jsFiddle here.

If deep copying worked, the output would be "Curious George" and not "Ender's Game". How can I make a deep copy? An answer to this question indicates that $.extend(true, [], obj) creates a deep copy. Yet my example shows that it doesn't.

function Person(){}
Person.prototype.favorite_books = [];

var george = new Person();
george.favorite_books = ["Curious George"];

var kate = new Person();
kate.favorite_books = ["The Da Vinci Code", "Harry Potter"];

var people = [kate, george];

var people_copy = $.extend(true, [], people);
people_copy[0].favorite_books[0] = "Ender's Game";

$('#text').text(people[0].favorite_books[0]);

SOLUTION

I updated the jsFiddle. It turns out I need to deep copy each object in the array individually if the object is a custom object (that is, $.isPlainObject returns false).

Upvotes: 16

Views: 29570

Answers (3)

Chtioui Malek
Chtioui Malek

Reputation: 11515

This is how I've done it after trying many approaches:

var newArray = JSON.parse(JSON.stringify(orgArray));

This will create a new deep copy, not a shallow copy.

Also this obviously will not clone events and functions, but the good thing is you can do it in one line, and it can be used for any king of object (arrays, strings, numbers, objects, etc.).

Upvotes: 9

zerkms
zerkms

Reputation: 254944

And now here is the real answer:

At the moment jQuery can only clone plain JavaScript Objects, while you're using custom ones. And that's obvious, since jQuery cannot know how exactly to instantiate a new custom object. So this works as expected:

var george = {};
george.favorite_books = ["Curious George"];

var kate = {};
kate.favorite_books = ["The Da Vinci Code", "Harry Potter"];

var people = [kate, george];

var people_copy = $.extend(true, [], people);

console.log(people_copy[0].favorite_books == people[0].favorite_books);

Reference to a jQuery code: https://github.com/jquery/jquery/blob/master/src/core.js#L305

See that it checks if it's jQuery.isPlainObject(copy) or it's an array. Otherwise it performs just a reference copy.

Upvotes: 21

Adam Jenkins
Adam Jenkins

Reputation: 55643

Interesting....it doesn't look like it deep copies arrays.

You have to deep copy each object individually.

var people_copy = [];
$.each(people,function(i,obj) {
    people_copy.push($.extend(true,{},obj)); 
});

EDIT: Sure, look at this fork of the OP's fiddle:

http://jsfiddle.net/s2bLv/4/

Upvotes: 4

Related Questions