最初に
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)
LodashやRamdaなどの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"]
#最後に
ここまでお読みいただきありがとうございました。
他の方法がございましたら、ぜひコメント欄にシェアしてください。
また、文法ミスや誤字がありましたら、編集リクエストでご意見をいただければと思います。