Heim  >  Fragen und Antworten  >  Hauptteil

Das Ändern einer Kopie eines JavaScript-Objekts führt zu Änderungen am Originalobjekt

<p>Ich kopiere <code>objA</code> nach <code>objB</code></p> <pre class="brush:php;toolbar:false;">const objA = { prop: 1 }, const objB = objA; objB.prop = 2; console.log(objA.prop); // protokolliert 2 statt 1</pre> <p>Arrays haben auch das gleiche Problem</p> <pre class="brush:php;toolbar:false;">const arrA = [1, 2, 3], const arrB = arrA; arrB.push(4); console.log(arrA.length); // `arrA` hat 4 statt 3 Elemente.</pre> <p><br /></p>
P粉765684602P粉765684602419 Tage vor469

Antworte allen(2)Ich werde antworten

  • P粉394812277

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

    总而言之,为了澄清起见,有四种复制 JS 对象的方法。

    1. 普通副本。当您更改原始对象的属性时,复制的对象的属性也会更改(反之亦然)。
    const a = { x: 0}
    const b = a;
    b.x = 1; // also updates a.x
    
    1. 浅拷贝。原始对象和复制对象的顶级属性将是唯一的。不过,嵌套属性将在两个对象之间共享。使用展开运算符 ...{}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. 深层副本。所有属性对于原始对象和复制对象都是唯一的,甚至是嵌套属性。对于深拷贝,请将对象序列化为 JSON 并将其解析回 JS 对象。
    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. 完整深拷贝。使用上述技术,JSON 中无效的属性值(如函数)将被丢弃。如果您需要深层复制并保留包含函数的嵌套属性,您可能需要查看像 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. 使用Object.create()确实创建了一个新对象。这些属性在对象之间共享(更改其中一个也会更改另一个)。与普通副本的区别在于,属性被添加到新对象的原型 __proto__ 下。当您从不更改原始对象时,这也可以用作浅拷贝,但我建议使用上述方法之一,除非您特别需要这种行为。

    Antwort
    0
  • P粉520545753

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

    很明显,您对语句 var tempMyObj = myObj; 的作用存在一些误解。

    在 JavaScript 中,对象是通过引用(更准确地说是引用的值)传递和分配的,因此 tempMyObjmyObj 都是对同一对象的引用。

    这是一个简化的插图,可以帮助您直观地了解正在发生的事情

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

    正如您在赋值后所看到的,两个引用都指向同一个对象。

    如果您需要修改其中一个而不是另一个,则需要创建副本

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

    旧答案:

    这里有几种创建对象副本的其他方法

    由于您已经在使用 jQuery:

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

    使用普通 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);

    请参阅此处此处

    Antwort
    0
  • StornierenAntwort