76

The below first logs 0, and then logs 1. How do I store a copy of the object, rather than a reference to it?

debug.log(vi.details.segment);
vi.nextSegment = vi.details;
vi.nextSegment.segment++;
debug.log(vi.details.segment);
informatik01
  • 16,038
  • 10
  • 74
  • 104
Matrym
  • 16,643
  • 33
  • 95
  • 140

7 Answers7

151

To clone an object in jQuery:

var vi.nextSegment = jQuery.extend({}, vi.details);

NOTE: The above is a shallow copy: any nested objects or arrays will be copied by reference - meaning any changes you make to vi.nextSegment.obj[prop] will be reflected in vi.details.obj[prop]. If you want a completely new object which is completely separate from the original, you will need to do a deep copy (pass true as the first parameter):

var vi.nextSegment = jQuery.extend(true, {}, vi.details);

To read up more on extend, see here.

Ryan Wheale
  • 26,022
  • 8
  • 76
  • 96
Mike Lewis
  • 63,433
  • 20
  • 141
  • 111
  • 11
    That isn't a deep copy. `var a = {b: [1, 2]}; $.extend({}, a).b[0] = 'test';` and `a.b[0]` will be changed to `'test'`. To do a deep copy, put `true` as the first argument: `$.extend(true, {}, a);` – Reid Mar 19 '11 at 20:25
  • 6
    One gothcha that just got me: `jQuery.extend(true, {}, obj);` will create a copy. `jQuery.extend(true, obj, {});` will not. – worldsayshi Apr 21 '13 at 21:41
  • @worldsayshi : I wish I saw your comment sooner. Having headaches on this for weeks. Thanks a lot. – nicolas Oct 09 '14 at 21:58
  • 1
    brilliant, guys! Just what I needed! – curveball Mar 10 '17 at 12:47
35

Take a look at the post: What is the most efficient way to clone a javascript object

As per John Resig's answer:

// Shallow copy
var newObject = jQuery.extend({}, oldObject);

// Deep copy
var newObject = jQuery.extend(true, {}, oldObject);

More information can be found in the jQuery documentation.

Community
  • 1
  • 1
Scoobler
  • 9,696
  • 4
  • 36
  • 51
8

This worked better for me cloning an object using jQuery "parseJSON()" and "JSON.stringify()"

$.ajax({
  url: 'ajax/test.html',
  dataType: 'json',
  success: function(data) {
    var objY = $.parseJSON(JSON.stringify(data));
    var objX = $.parseJSON(JSON.stringify(data));
  }
});

Cloning data object in objX & objY are two different object, you do no have to mess up with the "by reference" problem

Gracias!

Mecalito
  • 795
  • 11
  • 14
7

Another way to clone object is

newObj = JSON.parse(JSON.stringify(oldObj));

But be careful if it's contains dates. JSON.parse will return date.toString() instead of date in that case.

MarkosyanArtur
  • 1,359
  • 13
  • 10
3

This is how I copy elements several times:

First I have a template:

<div class="forms-container">
    <div class="form-template">
        First Name <input>
         .. a lot of other data ...
        Last Name <input>
     <div>
     <button onclick="add_another();">Add another!</button>
<div>

Now, the JavaScript:

function add_another(){
    jQuery(".form-template").clone().appendTo(".forms-container");
}
2

Try Immutable.js :

Since jQuery mostly deals with DOM Elements, it may not be the right tool for the job. Immutable.js is a 56 kb (minified) library created by Facebook.

// roughly implementing
import Immutable from 'immutable'
//
const oldObj = { foo: 'bar', bar: 'baz' }
// create a map from the oldObj and then convert it to JS Object
const newObj = Immutable.Map(oldObj).toJS()

This way you would have effectively cloned newObj from oldObj. Basically, if you don't have a Map already, then we need to create a Map first. Map is like a blue-print that we work with to create copies.

References :

Home - Immutable

Docs - Immutable Docs

GitHub - Immutable@GitHub

Good Luck.

Aakash
  • 21,375
  • 7
  • 100
  • 81
1

If you need to keep you initial object but need to override your data with your new options, you can pass multiple objects to $.extend (jQuery) with true on first option:

var opts_default = {opt1: true, opt2: false};
var opts_new = {opt1: false};
var opts_final = $.extend(true, {}, opts_default, opts_new);
Guillaume
  • 443
  • 5
  • 11