修改JavaScript对象的副本会导致原始对象发生更改

Val*_*bha 38 javascript copy object

我正在复制myObjtempMyObj

var tempMyObj = myObj;
Run Code Online (Sandbox Code Playgroud)

tempMyObj.entity是一个对象数组.我正在tempMyObj.entity根据某些条件进行修改.问题是如果我修改tempMyObj.entitymyObj.entity也正在修改.

for (j = 0; j < myObj.length; j++) {
    if (myObj[j].type == "TableShape") {
        var dupEntites = new Array();
        for (i = 0; i < myObj[j].entities.length; i++) {
            if (chk.value != myObj[j].entities[i].id) {
                var obj = {};
                obj.text = myObj[j].entities[i].text;
                obj.id = myObj[j].entities[i].id;
                dupEntites.push(obj);
            }
            else {
                if (chk.checked)
                {
                    var obj = {};
                    obj.text = myObj[j].entities[i].text;
                    obj.id = myObj[j].entities[i].id;
                    dupEntites.push(obj);
                }
            }
        }
        tempMyObj[j].entities = dupEntites;
    }
}
Run Code Online (Sandbox Code Playgroud)

rob*_*bmj 74

很明显,你对这个陈述的var tempMyObj = myObj;作用有一些误解.

在JavaScript对象传递,并通过引用(更准确的基准的值)分配,所以tempMyObjmyObj是同一个对象都引用.

这是一个简化的插图,可以帮助您可视化正在发生的事情

// [Object1]<--------- myObj

var tempMyObj = myObj;

// [Object1]<--------- myObj
//         ^ 
//         |
//         ----------- tempMyObj
Run Code Online (Sandbox Code Playgroud)

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

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

// [Object1]<--------- myObj

const tempMyObj = Object.assign({}, myObj);

// [Object1]<--------- myObj
// [Object2]<--------- tempMyObj
Run Code Online (Sandbox Code Playgroud)

旧答案:

以下是创建对象副本的其他几种方法

既然你已经在使用jQuery了:

var newObject = jQuery.extend(true, {}, myObj);
Run Code Online (Sandbox Code Playgroud)

使用vanilla 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);
Run Code Online (Sandbox Code Playgroud)

看到这里这里

  • `Object.assign({}, myObj);` 没有为我创建副本。相反,“var tempMyObj = Object.create(myObj);”有效。 (4认同)
  • 没问题!当我对已经回答的问题进行如此广泛的编辑时,我会尝试跟进.:) (2认同)

jna*_*aas 37

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

\n
    \n
  1. 普通副本。当您更改原始对象的属性时,复制的对象的属性也会更改(反之亦然)。
  2. \n
\n
const a = { x: 0}\nconst b = a;\nb.x = 1; // also updates a.x\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 拷贝。原始对象和复制对象的顶级属性将是唯一的。不过,嵌套属性将在两个对象之间共享。使用展开运算符...{}Object.assign()
  2. \n
\n
const a = { x: 0, y: { z: 0\xc2\xa0} };\nconst b = {...a}; // or const b = Object.assign({}, a);\n\nb.x = 1; // doesn\'t update a.x\nb.y.z = 1; // also updates a.y.z\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 拷贝。所有属性对于原始对象和复制对象都是唯一的,甚至是嵌套属性。对于深拷贝,将对象序列化为 JSON 并将其解析回 JS 对象。
  2. \n
\n
const a = { x: 0, y: { z: 0 } };\nconst b = JSON.parse(JSON.stringify(a)); \n\nb.y.z = 1; // doesn\'t update a.y.z\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 完整的深拷贝。使用上述技术,JSON 中无效的属性值(如函数)将被丢弃。如果您需要深层复制并保留包含函数的嵌套属性,您可能需要查看像lodash.
  2. \n
\n
import { cloneDeep } from "lodash"; \nconst a = { x: 0, y: { z: (a, b) => a + b } };\nconst b = cloneDeep(a);\n\nconsole.log(b.y.z(1, 2)); // returns 3\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 使用Object.create()确实创建了一个新对象。这些属性在对象之间共享(更改其中一个也会更改另一个)。与普通副本的区别在于,属性被添加到新对象的原型下__proto__。当您从不更改原始对象时,这也可以用作浅拷贝,但我建议使用上述方法之一,除非您特别需要这种行为。
  2. \n
\n

  • 请注意,使用 JSON.stringify 深度复制对象将丢弃 JSON 中无效的任何值(如函数)以及任何不可枚举的值。 (4认同)

Ahm*_*asy 19

deep clone object with JSON.parse() and JSON.stringify

// Deep Clone
obj = { a: 0 , b: { c: 0}};
let deepClone = JSON.parse(JSON.stringify(obj));
Run Code Online (Sandbox Code Playgroud)

refrence: this article

Better reference: this article


小智 7

尝试使用如下所述的 create() 方法。

var tempMyObj = Object.create(myObj);
Run Code Online (Sandbox Code Playgroud)

这将解决问题。


小智 7

使用三个点来分散新变量中的对象

const a = {b: 1, c: 0};
let d = {...a};
Run Code Online (Sandbox Code Playgroud)


gue*_*314 6

尝试使用$.extend()

但是,如果您想保留两个原始对象,可以通过传递一个空对象作为目标来实现:

var object = $.extend({}, object1, object2);


var tempMyObj = $.extend({}, myObj);
Run Code Online (Sandbox Code Playgroud)

  • JavaScript 现在有一个类似的内置函数,[`Object.assign()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)。用法示例:`Object.assign({}, myObj)`。 (7认同)