2017-12-04 16 views
0

なぜこの現象が起こっているのかわかりません。私はオブジェクトを定義し、このオブジェクトの3の配列を作ると言うことができます。配列内のオブジェクトを変更すると、オブジェクトのすべてのインスタンスに影響しますか?誰かがこれがなぜなのか説明できますか?また、オブジェクトの独立した "Copies"を持つ配列を作成して、目的の動作を得るにはどうすればよいですか?ありがとう!プリミティブ(文字列、数値、ブール値、ヌルシンボル、未定義)とは対照的に配列内のオブジェクトを操作すると、配列外のオブジェクトが変更されますか?

testObject = {"value1":"a","value2":"b"}; 
objArray = []; 
for(i=0; i < 3; i++){ 
    var newobj = testObject; //make a new testObject 
    objArray.push(newobj); //push new object to array 
    } 
delete objArray[0].value2 // Desired, delete value 2 ONLY from array object 0 
objArray[2].value2 //Undefined? Why is value2 missing from object 2 
testObject.value2 //Undefined? Why is value2 missing from original object? 
+0

* "' var newobj = testObject; //新しいtestObjectを作成する "*:コメントが間違っています。これは新しいオブジェクトを作成するのではなく、既存のオブジェクトを共有します。 – trincot

+0

[JavaScriptオブジェクトを正しくクローンするにはどうすればいいですか?](https://stackoverflow.com/questions/728360/how-do-i-correctly-clone-a-javascript-object) – dprogramz

+0

ところで、 value1'と 'value2'は単にプレースホルダの名前か、実際には配列のようなObjectを使うつもりですか? –

答えて

2

、JavaScriptでオブジェクトがreferenceによって渡されます。変数は、これらのオブジェクトのプレースホルダ/ポインタとして機能します。突然変異のリスクなしにオブジェクトのコピーを作成するには、spread(禁じる互換)を使用したい:

const newObject = { ...testObject }; 

や伝統、Object.assign()を、元testObjectの可変性を回避するために、リテラル空のオブジェクトを渡す:

const newObject = Object.assign({}, testObject); 

限り深いクローニング、MDNはJSON.parse()JSON.stringify()の組み合わせを使用することを提案します。たとえば、次のようになります。

+0

良いキャッチ。一定。 –

+0

このALMOSTは機能しますが、オブジェクト内にオブジェクトがある場合は同じ問題が発生します。それらを独立させるにはどうすればいいですか? Object Assignをレイヤーする必要がありますか?例: testObject = {"value:" a "、" Other ":{ testObject.Other.value2 //定義されていません – dprogramz

+0

私の更新された回答を確認してください。 –

0

ループ内で同じオブジェクトの参照を何度も繰り返しています。

for(i=0; i < 3; i++){ 
    var newobj = testObject; //no new object,same object's reference again 
    objArray.push(newobj); //push new object to array 
    } 

それは

JavaScriptでオブジェクトを作成するときは、あなたが実際にそのオブジェクトへの参照 を作成している
for(i=0; i < 3; i++){ 
    var newobj = {"value1":"a","value2":"b"}; //make a new testObject 
    objArray.push(newobj); //push new object to array 
    } 
0

でなければなりません。これを変数に格納して渡すことができます。おそらくそれを配列に追加します。オブジェクト参照の操作を行うと、参照が指す元のオブジェクトが検索され、更新されます。したがって、.pushを使用すると、新しいオブジェクトを作成するのではなく、単にそのオブジェクトへの参照をプッシュします。ある場所で更新すると、他の場所やその参照を割り当てた他の場所で更新されます。

オブジェクトを新しいオブジェクトにコピーすることは、一般的にクローニングと呼ばれます。さまざまな結果を持つJavaScriptでオブジェクトをクローン化するには、さまざまな方法があります。

var newobj = { ...testObject }は、他の回答が示すように使用できます。このスプレッド演算子は基本的にtestObjectのプロパティをコピーし、新しいオブジェクト(外側の{}で宣言されている)を作成します。そのの新しいオブジェクトへの参照は、newobjに割り当てられます。あなたがこれを行うと考えることができます:

var newobj = { 
    value1: testObject.value1, 
    value2: testObject.value2, 
}; 

ただし、あなたはこれがあなたのクローニングの一つだけのレベルを与えるということを覚えておいてください。つまり、オブジェクトに他のオブジェクトが含まれている場合、そのオブジェクトの参照がそのオブジェクトの複製ではなくプロパティとして割り当てられます。例えば:あなたが持っていたとしましょう:

var testObject = { obj: { a: "b" } }; 
var newobj = { ...testObject }; 
delete testObject.obj.a; 
console.log(newobj); // { obj: {} } 

これを解決するためには、JavaScriptで再帰的にもオブジェクトであるオブジェクトのプロパティをクローニングすることによって行うことができ深いクローンと呼ばれるものを行う必要があります。 lodashなどのライブラリや自家製機能を含め、これを行う方法はたくさんあります。 SOの一例:testObjectは他newobjが誘導されるオブジェクト・テンプレートまたは初期状態のようなものであると考えられる場合What is the most efficient way to deep clone an object in JavaScript?

最後に、それが機能を使用する方が理にかなってあります。

function newObjFactory() { 
    return { 
    value1: "a", 
    value2: "b", 
    }; 
} 

その後、var newobj = newObjFactory()を実行すると、呼び出されるたびに関数によって新しいオブジェクトが作成され、returnが編集されるので、毎回新しいオブジェクトを取得します。

関連する問題