Home  >  Q&A  >  body text

Modifying a copy of a JavaScript object causes changes to the original object

<p>I'm copying <code>objA</code> to <code>objB</code></p> <pre class="brush:php;toolbar:false;">const objA = { prop: 1 }, const objB = objA; objB.prop = 2; console.log(objA.prop); // logs 2 instead of 1</pre> <p>Arrays also have the same problem</p> <pre class="brush:php;toolbar:false;">const arrA = [1, 2, 3], const arrB = arrA; arrB.push(4); console.log(arrA.length); // `arrA` has 4 elements instead of 3.</pre> <p><br /></p>
P粉765684602P粉765684602419 days ago463

reply all(2)I'll reply

  • P粉394812277

    P粉3948122772023-08-28 17:35:35

    To summarize, just to clarify, there are four ways to copy a JS object.

    1. Normal copy. When you change the properties of the original object, the properties of the copied object also change (and vice versa).
    const a = { x: 0}
    const b = a;
    b.x = 1; // also updates a.x
    
    1. Shallow copy. The top-level properties of the original and copied objects will be unique. However, nested properties will be shared between the two objects. Use the spread operator ...{} or Object.assign().
    const a = { x: 0, y: { z: 0 } };
    const b = {...a}; // or const b = Object.assign({}, a);
    
    b.x = 1; // doesn't update a.x
    b.y.z = 1; // also updates a.y.z
    
    1. Deep copy. All properties are unique to the original and copied objects, even nested properties. For a deep copy, serialize the object to JSON and parse it back into a JS object.
    const a = { x: 0, y: { z: 0 } };
    const b = JSON.parse(JSON.stringify(a)); 
    
    b.y.z = 1; // doesn't update a.y.z
    
    1. Full Deep Copy. Using the above technique, invalid property values ​​(such as functions) in JSON are discarded. If you need to deep copy and preserve nested properties containing functions, you may want to look at a utility library like lodash.
    import { cloneDeep } from "lodash"; 
    const a = { x: 0, y: { z: (a, b) => a + b } };
    const b = cloneDeep(a);
    
    console.log(b.y.z(1, 2)); // returns 3
    
    1. Using Object.create() indeed creates a new object. These properties are shared between objects (changing one changes the other). The difference from a normal copy is that the properties are added to the new object's prototype __proto__. This can also be used as a shallow copy when you never change the original object, but I recommend using one of the above methods unless you specifically need this behavior.

    reply
    0
  • P粉520545753

    P粉5205457532023-08-28 12:57:02

    Obviously, you have some misunderstanding about what the statement var tempMyObj = myObj; does.

    In JavaScript, objects are passed and allocated by reference (more precisely, the value of the reference), so tempMyObj and myObj are both references to the same object.

    This is a simplified illustration to help you visualize what is going on

    // [Object1]<--------- myObj
    
    var tempMyObj = myObj;
    
    // [Object1]<--------- myObj
    //         ^ 
    //         |
    //         ----------- tempMyObj

    As you can see after the assignment, both references point to the same object.

    If you need to modify one but not the other, you will need to create a copy.

    // [Object1]<--------- myObj
    
    const tempMyObj = Object.assign({}, myObj);
    
    // [Object1]<--------- myObj
    // [Object2]<--------- tempMyObj

    Old answer:

    Here are several other ways to create copies of objects

    Since you are already using jQuery:

    var newObject = jQuery.extend(true, {}, myObj);

    Use plain JavaScript

    function clone(obj) {
        if (null == obj || "object" != typeof obj) return obj;
        var copy = obj.constructor();
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
        }
        return copy;
    }
    
    var newObject = clone(myObj);

    See here and here

    reply
    0
  • Cancelreply