LoginSignup
1
3

More than 3 years have passed since last update.

JavaScriptで配列をコピーする方法まとめ(多次元配列含む)

Last updated at Posted at 2021-03-17

最初に

JavaScriptのオブジェクトをコピーする方法については、こちらの記事をクリックしてください。
本記事では配列のコピー方法を紹介しています。

JavaScriptでは、大別してプリミティブ型(データ型)とノンプリミティブ型(構造型)の二つがあります。string・number・booleanなどはプリミティブ型、オブジェクト・配列・関数などはノンプリミティブ型と分けています。(MDN参照

プリミティブ型データに対して、簡単にx = yをすると値渡しのコピーができますが、ノンプリミティブ型データにはこのようにコピーすると参照渡しのコピー(データの置き場所)になります。

コード例:

// プリミティブ型
let name = "Kimmy"
let nameCopy = name

nameCopy = "Qiita"

// 値渡しのコピーなのでanotherNameの値は変更されていません
console.log(name)  // Kimmy
console.log(nameCopy)  //Qiita

// ノンプリミティブ型
let animals = ['lion', 'owl', 'dog'];
let animalsCopy = animals

animalsCopy[0] = "cat"

// 参照渡しのコピーなので、一方を変更すると両方に変更が反映されます
console.log(animals)  // ["cat", "owl", "dog"]
console.log(animalsCopy)  // ["cat", "owl", "dog"]

コピー方法について

コピーには浅いコピーと深いコピー2つがあります。
- 浅いコピー:1段階のデータのみ値渡しのコピーになり、2段階以上のデータには参照渡しのコピーになります。
- 深いコピー:多階層のデータでも、オブジェクトは最も深いところまですべての値をコピーします。
なので、データの深さを考える必要があります。

浅いコピー(Shallow Copy)

以下animal配列のような階層を持っていないデータを例としてコピーを行います。

concat()

let animal = ['lion', 'owl', 'dog'];
let animalCopy = [].concat(animal);

animalCopy.push('cat');

console.log(animal); // ["lion", "owl", "dog"]
console.log(animalCopy); // ["lion", "owl", "dog", "cat"]

slice()

let animal = ['lion', 'owl', 'dog'];
let animalCopy = animal.slice();

animalCopy.push('cat');

console.log(animal); // ["lion", "owl", "dog"]
console.log(animalCopy); // ["lion", "owl", "dog", "cat"]

Object.assign()

配列はオブジェクトから派生した構造的な型なので、Object.assign()も使えます。

let animal = ['lion', 'owl', 'dog'];
let animalCopy = Object.assign([], animal);

animalCopy.push('cat');

console.log(animal); // ["lion", "owl", "dog"]
console.log(animalCopy); // ["lion", "owl", "dog", "cat"]

Array.from()

Array.from()はES2015で追加されたメソッドです。

let animal = ['lion', 'owl', 'dog'];
let animalCopy = Array.from(animal);

animalCopy.push('cat');

console.log(animal); // ["lion", "owl", "dog"]
console.log(animalCopy); // ["lion", "owl", "dog", "cat"]

スプレッド構文

ES2015で追加されたスプレッド構文を利用した浅いコピーができます。

let animal = ['lion', 'owl', 'dog'];
let animalCopy = [...animal];

animalCopy.push('cat');

console.log(animal); // ["lion", "owl", "dog"]
console.log(animalCopy); // ["lion", "owl", "dog", "cat"]

深いコピー(Deep Copy)

LodashRamdaなどのJavaScriptライブラリーを使って、深いコピーもできますが、今回はライブラリーなしの方法を紹介します。

function cloneArray(array) {
  let clone = [];
  array.forEach((item) =>
    Array.isArray(item) ? clone.push(cloneArray(item)) : clone.push(item)
  );
  return clone;
}
let animal = [["dog", "cat"], ["lion", "tiger"], "owl"];

let animalClone = cloneArray(animal); // 深いコピー
let faultyClone = [...animal] // 浅いコピーの一つ

animal[0][0] = "dinosaur"; // "dog"から"dinosaur"に変更される

console.log(animal); // ["dinosaur", "cat"], ["lion", "tiger"], "owl"]

// 浅いコピーはdinosaurに変更される
console.log(faultyClone); // ["dinosaur", "cat"], ["lion", "tiger"], "owl"]

// 深いコピーは変更なし
console.log(animalClone); // ["dog", "cat"], ["lion", "tiger"], "owl"]

最後に

ここまでお読みいただきありがとうございました。
他の方法がございましたら、ぜひコメント欄にシェアしてください。
また、文法ミスや誤字がありましたら、編集リクエストでご意見をいただければと思います。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3