63473


# 前置き

javascriptにてオブジェクト配列をスプレッド構文でコピーした際、  
obj_aryとobj_ary_copyは同一でないにもかかわらず参照が保たれています。

[code]

    const obj_ary = [
      { 'aaa': 100 },
      { 'bbb': 200 }
    ];
    const obj_ary_copy = [...obj_ary];
    
    console.log(obj_ary === obj_ary_copy); // false
    
    obj_ary["0"].aaa = 300;
    console.log(obj_ary_copy);    // [{"aaa":300},{"bbb":200}] ← obj_ary_copy[0].aaaも変化している
    
[/code]

# 疑問点

## 01

なぜ、このようなシャローコピーとディープコピーの間の子のようなコピー方法が存在するのですか？  
(もし何らかの有効な使い方があれば教えて頂きたいです)

## 02

参照を保ったコピーという観点 **のみ** で考えるならば、

[code]

    const obj_ary_copy = obj_ary;
    
[/code]

のような直接的な値の代入とスプレッド構文によるコピーで何らかの差はありますか？


CC BY-SA 4.0
2020-03-01T09:00:58.193
63471
2020-03-01T09:54:59.847
2020-03-01T09:09:29.067
9616
question
javascript node.js
スプレッド構文での配列コピー時の参照について


## 01

あなたが作成された例は典型的な「シャローコピー」の例であり、「シャローコピーとディープコピーの間」ではありません。

「シャローコピー」と言うのは「器だけのコピーを行い、器に入れられている個々の要素についてはコピーしない」ことを表します。まさにあなたの例の通りです。「器」はコピーされているので、`obj_ary
===
obj_ary_copy`は成立しませんが、個々の要素はコピーされないので、`obj_ary[0]`と`obj_ary_copy[0]`は同じモノを指します。

これが、 **普通にシャローコピーを行った場合の挙動**
です。「何らかの有効な使い方」があるからこうしているのではなく、普通にシャローコピーを行うとこうなるのです。

## 02

「参照を保ったコピーという観点 **のみ** 」と言うのが、何をどこまで制限するのかよく分からないのですが、

[code]

    const obj_ary_copy = obj_ary;
    
[/code]

のように、参照のみが渡される場合は、「シャローコピー」とさえ呼びません。器さえコピーされずに`obj_ary_copy`も`obj_ary`も同じ「器」を指している、と言うことになります。

この場合、`obj_ary[0] = {'ccc': 300};`とやった後、 `obj_ary_copy[0]`を見れば、`{'ccc':
300}`になっているはずです。`const obj_ary_copy =
[...obj_ary];`とかやって「器のコピー」をした場合とは明らかに挙動が異なります。

* * *

「個々の要素までコピーするのがディープコピー」と言っても、あなたが挙げられた例のように「個々の要素自体がまた『器』として使われている」と言う状態になっている場合、どこまで深くコピーすれば十分なのか、機械的には分からないこともあるため、単純な配列のコピー作成では(スプレッド構文を使おうが、他の方法であろうが)ディープコピーは行われないことが多いのです。

なお、少し前に別質問のために調べたのですが、「シャローコピー」「ディープコピー」と言う言葉については、誤った解説記事が多数検索結果の上位に来たりします。上位にきたから正しいはずなどと思い込まずに正しい記述を見つけられるようにしてください。


CC BY-SA 4.0
2020-03-01T09:54:59.847
63473
2020-03-01T09:54:59.847
13972
63471
answer