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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了修改JavaScript对象的副本会导致原始对象发生更改相关的知识,希望对你有一定的参考价值。

我正在将myObj复制到tempMyObj

var tempMyObj = myObj;

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;
    }
}
答案

很明显,你对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);

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

herehere

另一答案

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

var tempMyObj = Object.create(myObj);

这将解决问题。

另一答案

尝试使用$.extend()

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

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


var tempMyObj = $.extend({}, myObj);
另一答案

这可能非常棘手,让我试着用一个简单的方法。当您将一个变量“复制”到javascript中的另一个变量时,实际上并没有将其值从一个变量复制到另一个变量,而是分配给复制的变量,即对原始对象的引用。要实际制作副本,您需要创建一个新的对象使用

棘手的部分是因为为复制的变量分配新值和修改其值之间存在差异。为复制变量分配新值时,您将删除引用并将新值分配给副本,但是,如果仅修改副本的值(不指定新值),则需要修改复制和原件。

希望这个例子有帮助!

let original = "Apple";
let copy1 = copy2 = original;
copy1 = "Banana";
copy2 = "John";

console.log("ASSIGNING a new value to a copied variable only changes the copy. The ogirinal variable doesn't change");
console.log(original); // Apple
console.log(copy1); // Banana
console.log(copy2); // John 

//----------------------------

original = { "fruit" : "Apple" };
copy1 = copy2 = original;
copy1 = {"animal" : "Dog"};
copy2 = "John";

console.log("
 ASSIGNING a new value to a copied variable only changes the copy. The ogirinal variable doesn't change");
console.log(original); //{ fruit: 'Apple' }
console.log(copy1); // { animal: 'Dog' }
console.log(copy2); // John */

//----------------------------
// HERE'S THE TRICK!!!!!!!

original = { "fruit" : "Apple" };
let real_copy = {};
Object.assign(real_copy, original);
copy1 = copy2 = original;
copy1["fruit"] = "Banana"; // we're not assiging a new value to the variable, we're only MODIFYING it, so it changes the copy and the original!!!!
copy2 = "John";


console.log("
 MODIFY the variable without assigning a new value to it, also changes the original variable")
console.log(original); //{ fruit: 'Banana' } <====== Ops!!!!!!
console.log(copy1); // { fruit: 'Banana' }
console.log(copy2); // John 
console.log(real_copy); // { fruit: 'Apple' } <======== real copy!

以上是关于修改JavaScript对象的副本会导致原始对象发生更改的主要内容,如果未能解决你的问题,请参考以下文章

修改 Javascript 对象副本会使原始对象在 Angular 5 Reactive Forms 中发生变化

如何在修改其副本时避免更新原始数组? [复制]

为什么在似乎是数据副本的操作上修改原始数据?

修改numpy中的索引对象

Python:附加原始对象与附加对象副本[重复]

修改嵌套列表的副本会修改原始列表[重复]