LINEで現役エンジニアに直接質問してみよう!登録無料

JavaScriptの配列をディープコピーする方法2種類

javascriptの配列をコピーする方法を2種類紹介します。

コピーする方法は2種類あります。

// concatを使ったコピー方法
var dist = [].concat(src);

// sliceを使ったコピー方法
var dist = src.slice(0, src.length);

array1 array2がお互い独立したデータになるように、コピーする方法を紹介します。今回は、concat sliceを用いた配列のコピー方法を2種類紹介します。

なぜ配列のコピーは変数に入れるだけで出来ないのか?

javascriptの配列はオブジェクト(参照型)であり、単に変数に入れ直すだけではコピーすることはできません。なぜなら変数には、オブジェクトデータそのものではなく、オブジェクトへの参照(データそのものではなく、データへのメモリアドレス)が格納されているからです。

だから、両者とも同じメモリ上のデータを見ていることになります。

// 配列を作成し、array2に代入する
const array1 = [0, 1, 2, 3, 4];
const array2 = array1;

// ここでarray2を変更すると、、、
array2[0] = 100;

// array1も変更されている。
console.log(array1);

2つの変数array1 array2どちらを書き換えても、参照しているデータは同じものなので、コピー先もコピー元も変数の内容が変更されます。ちなみに、このコピーのことを「シャローコピー」といいます。

コピー方法1: concatを使う方法

concat()を使った配列のコピーは、下記のような書き方になります。

var dist = [].concat(src);

concat()とは、引数に渡した配列を連結し、新しい配列を生成するメソッドです。

// 配列を作成し、array2にコピーします。
const array1 = [0, 1, 2, 3, 4];
const array2 = [].concat(array1);

// ここでarray2を変更すると、、、
array2[0] = 100;

console.log(array1);
console.log(array2);

また、下記のような書き方も出来ます。

// 配列を作成し、array2にコピーします。
const array1 = [0, 1, 2, 3, 4];
const array2 = array1.concat();

しかし、個人的は最初の書き方がオススメです。理由は、javascriptのオブジェクトのconcatと同じ用法でつかえるからです。

javascriptのオブジェクト({ key: 'value' }のようなデータ)にも、concatというメソッドがあります。度々、2つのオブジェクトを合体させつつ、同じキーは上書きするプログラムを書く部分が登場します。concatを使うと、下記のようにコンパクトに書けます。

const dist = {}.concat(src, {
    key: 'value'
});

配列コピーのときと、書き方が似ていますよね?私はこのように書けば、混乱せずに済むようになるのでコレで統一しています。

コピー方法2: sliceを使う方法

slice()を使って配列のコピーをすることもできます。

var dist = src.slice(0, src.length);

sliceとは、引数に渡した開始インデックスから終了インデックスまでの要素を新しく切り出すメソッドです。切り出す過程で、新しくオブジェクトが生成させる特徴を利用します。

// 配列を作成し、array2にコピーします。
const array1 = [0, 1, 2, 3, 4];
const array2 = array1.slice(1, array1.length);

// ここでarray2を変更すると、、、
array2[0] = 100;

console.log(array1);
console.log(array2);

「シャローコピー」と「ディープコピー」

コピーする時によく使われる言葉として「シャローコピー」と「ディープコピー」があるので解説します。

「シャローコピー」とは?

シャローコピーとは、shallow(浅い) copy(コピー)という言葉から来ており、文字の通り「浅いコピー」をいう意味です。

一体何を指して浅いと区別するのかと言うと、配列の階層や実際のオブジェクトそのものまでの距離のことを言います。

例えば、「2次元配列、3次元配列と配列の階層が増えていったり」、「オブジェクトまでの参照(C言語のポインタのようなイメージ)の参照の、、、」と増えていくと距離が遠いと「より深い」と言う表現になります。

通常、シャローコピーというと、1次元配列のみをコピーする方法か、オブジェクトまでの参照をコピーする方法のどちらかを指す場合が多いです。

「ディープコピー」とは?

ディープコピーとは、deep(深い) copy(コピー)という言葉から来ており、「深いコピー」を表します。「シャローコピー」の反対ですね。

ディープコピーをすると、ネストされた多次元配列の全てを別オブジェクトとして生成します。そのため、処理が重くあまり使用されません。どうしてもコピーしないと都合が悪い場合のみ使うようにしましょう!

まとめ

  • 配列をコピーする方法はconcat()slice()を使う方法2種類ある。
  • 1次元配列のみをコピーする方法は「シャローコピー」と呼ばれる
  • 逆に多次元配列全てをコピーする方法は「ディープコピー」と呼ばれる

以上、テーブルの作成方法をアキ(@hackablejp)が解説しました!

この記事を書いた人

自身がプログラミングを独学で勉強し始めて躓いた経験を元に、これから勉強をする人に向けに「イラスト多めでわかりやすい記事」にこだわって情報を発信しています。

現在はフルスタックエンジニアとしてサービス開発などのお仕事をしています。