web-dev-qa-db-ja.com

JavaScriptオブジェクトのコピーを変更すると、元のオブジェクトが変更されます

myObjtempMyObjにコピーしています

var tempMyObj = myObj;

tempMyObj.entityはオブジェクトの配列です。いくつかの条件に基づいてtempMyObj.entityを変更しています。問題は、tempMyObj.entityを変更すると、myObj.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;
    }
}
33
Vallabha

ステートメント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);

here および here を参照してください

66
robbmj

下記のようなcreate()メソッドを使用してみてください。

var tempMyObj = Object.create(myObj);

これで問題が解決します。

4

$。extend() を使用してみてください:

ただし、元のオブジェクトを両方とも保持する場合は、空のオブジェクトをターゲットとして渡すことで保持できます。

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


var tempMyObj = $.extend({}, myObj);
3
guest271314

これは非常に難しいかもしれません。これを簡単な方法で試してみましょう。 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("\n 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("\n 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!
2
Marcio