質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

865閲覧

シャローコピー後に配列を変更するとメモリ上のデータはどうなるのか

maskmelon

総合スコア63

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/09/25 14:34

シャローコピーについて、コピー元のオブジェクトとコピー先のオブジェクトがメモリ上の同じデータを参照するものと理解しています。

シャローコピーを行うJavaScriptのsliceメソッドやconcatメソッドは元の配列を変更しませんが、同じデータを参照しているにも関わらずコピー後の配列に変更を加えても元の配列が影響を受けないというのがいまいちピンと来ません。

そもそも違うデータの入っている配列が2つ出来てしまうのだから、その時点でメモリ上の違うデータを参照することになってしまうような気がします。

ディープコピーが非破壊的で、シャローコピーが破壊的という組み合わせなら理解できるのですが。。

かなり初歩的な質問ですが、ご教授いただけますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

think49

2020/09/25 14:59

言葉だけの説明では不十分なので、あなたが説明している現象を確認可能なコードを質問文に入力してください。markdownで。
think49

2020/09/25 15:03

「破壊的/非破壊的」と「シャローコピー/ディープコピー」は全くの別概念と思いますが、それぞれの概念をどのように理解しているのでしょうか。
maskmelon

2020/09/25 15:43

シャローコピーが同じデータを参照しているなら変更を加えると元のデータも変更されてしまい、ディープコピーはデータそのものが違っているので変更の影響を受けないという意味合いで上のように述べたのですが、シャローコピーは配列そのものの参照が同じわけではなく要素の参照が同じという点を見落としていたようです。 今後質問文にはコードを含めるようにします。ご指摘ありがとうございます。
guest

回答1

0

ベストアンサー

配列のコピーを行うと、別の配列になります。
コピー元の配列要素がオブジェクトの場合は、コピー先の配列からもその同じオブジェクトを参照します。これが配列のシャローコピーと言うことです。

配列としては、別物であると言うことと、要素が同じオブジェクトを指していることとを混同しているのだと思います。

JavaScript

1obj = {"A": 1}; 2a = [obj]; 3b = a.slice(0); // 配列のシャローコピー:配列としては別物 4c = a; // 配列としては同じ物 5 6a[0]["A"] = 2; // オブジェクトの更新 7console.log(b[0]); // => {A: 2} ; a[0]とb[0]は同じオブジェクトを指している 8 9a[0] = {"B": 3}; // 配列の更新 10console.log(b[0]); // => {A: 2} ; 配列としては別物なのでa[0]に代入したオブジェクトはb[0]とは無関係 11console.log(c[0]); // => {B: 3} ; aとcは同じ配列を指している 12 13a = [1,2,3]; // 変数aに新しい配列を代入 14console.log(c[0]); // => {B: 3} ; cは最初の配列のまま

投稿2020/09/25 15:08

otn

総合スコア84423

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maskmelon

2020/09/25 15:37 編集

回答くださりありがとうございます。要素の参照先が同じということなんですね。ご指摘の通り誤解していたようです。 要素がオブジェクトではなく値の場合には完全なコピーになるということでしょうか? 例えば、 const arr1 = [1, 2, 3] const arr2 = arr1.concat([4, 5]) のような場合に、arr1が参照するメモリの上のデータとarr2が参照するメモリ上のデータの位置は異なっていますか?
otn

2020/09/25 16:02

ああ、constにするかletにするか後で考えようと思っていたら、どっちも付け忘れてました。 数値や文字列は、変更が出来ない(イミュータブル)(=代入し直ししか出来ない)なので、メモリ上で同じ場所であれ、別の場所であれ、処理結果は同じです。 私の書いた例で言うと、「オブジェクトの更新」に相当する操作がないので、「こっちを更新したらこっちにも反映」ということが起こりえません。変更方法は代入しかない。 > 要素がオブジェクトではなく値の場合には完全なコピーになるということでしょうか? 実装の中身は知りませんが、配列がもしすべてポインタ経由で値を指すようになっているのであれば、コピーは常にシャローコピーですね。少なくとも文字列はポインタ経由でコピー元もコピー先も同じ文字列を指していると思います。数値は特別扱いの可能性有り。
maskmelon

2020/09/26 01:38

理解できました。回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問