配列の複製
= だけで代入して複製
配列を = で代入すると、どちらか一方の要素の値が変わると双方の値が変わります。
let ary = [ '車寅次郎' , '諏訪さくら' , '諏訪博' , '諏訪満男' , 'タコ社長' , '御前様' ] ; let copyAry = ary ; // イコールで代入 copyAry[0] = '源吉' ; // 代入先の要素を変更 // 代入元の要素の値も変わる。 console.log( ary ) ; // (6) ['源吉', '諏訪さくら', '諏訪博', '諏訪満男', 'タコ社長', '御前様'] console.log( copyAry ) ; // (6) ['源吉', '諏訪さくら', '諏訪博', '諏訪満男', 'タコ社長', '御前様']
concat で複製
concat メソッドは配列を連結して新たな配列を返します。
引数を指定せずに concat を実行すると自身の配列だけが新たな配列として返されます。
let ary = [ '車寅次郎' , '諏訪さくら' , '諏訪博' , '諏訪満男' , 'タコ社長' , '御前様' ] ; let copyAry = ary.concat() ; // concatで新しい配列を作成して複製 copyAry[0] = '源吉' ; // 複製先の要素を変更 // 複製元の要素の値は変わらない。 console.log( ary ) ; // (6) ['車寅次郎', '諏訪さくら', '諏訪博', '諏訪満男', 'タコ社長', '御前様'] console.log( copyAry ) ; // (6) ['源吉', '諏訪さくら', '諏訪博', '諏訪満男', 'タコ社長', '御前様']
slice で複製
slice メソッドは引数で指定された要素を配列として返します。
引数を指定せずに slice を実行すると自身の配列だけが新たな配列として返されます。
let ary = [ '車寅次郎' , '諏訪さくら' , '諏訪博' , '諏訪満男' , 'タコ社長' , '御前様' ] ; let copyAry = ary.slice() ; // slice で新しい配列を作成して複製 copyAry[0] = '源吉' ; // 複製先の要素を変更 // 複製元の要素の値は変わらない。 console.log( ary ) ; // (6) ['車寅次郎', '諏訪さくら', '諏訪博', '諏訪満男', 'タコ社長', '御前様'] console.log( copyAry ) ; // (6) ['源吉', '諏訪さくら', '諏訪博', '諏訪満男', 'タコ社長', '御前様']
…Array で複製
…Array スプレッド構文*ES2015 を利用すると、もとの配列要素を展開して新しい配列を作成します。
let ary = [ '車寅次郎' , '諏訪さくら' , '諏訪博' , '諏訪満男' , 'タコ社長' , '御前様' ] ; let copyAry = [...ary] ; // スプレッド構文 で新しい配列を作成して複製 copyAry[0] = '源吉' ; // 複製先の要素を変更 // 複製元の要素の値は変わらない。 console.log( ary ) ; // (6) ['車寅次郎', '諏訪さくら', '諏訪博', '諏訪満男', 'タコ社長', '御前様'] console.log( copyAry ) ; // (6) ['源吉', '諏訪さくら', '諏訪博', '諏訪満男', 'タコ社長', '御前様']
Array.from で複製
Array.from*ES2015 を利用すると、もとの配列から新しい配列を作成します。
let ary = [ '車寅次郎' , '諏訪さくら' , '諏訪博' , '諏訪満男' , 'タコ社長' , '御前様' ] ; let copyAry = Array.from(ary) ; // Array.from で新しい配列を作成して複製 copyAry[0] = '源吉' ; // 複製先の要素を変更 // 複製元の要素の値は変わらない。 console.log( ary ) ; // (6) ['車寅次郎', '諏訪さくら', '諏訪博', '諏訪満男', 'タコ社長', '御前様'] console.log( copyAry ) ; // (6) ['源吉', '諏訪さくら', '諏訪博', '諏訪満男', 'タコ社長', '御前様']
シャローコピー(浅い複製)とディープコピー(深い複製)
concat / slice / スプレッド構文 / Array.from での複製はシャローコピー(浅い複製)となるので、多次元の配列の複製には注意が必要です。
let ary = [ [ '車寅次郎' , '渥美清' ] , [ '諏訪さくら' , '倍賞千恵子' ] , [ 'タコ社長' , '太宰久雄' ] , ] ; let copyAry = [...ary] ; // スプレッド構文 で新しい配列を作成して複製 copyAry[0][0] = '源吉' ; // 複製先の要素を変更 copyAry[0][1] = '佐藤蛾次郎' ; // 複製先の要素を変更 // 複製元の要素の値も変わる。 (車寅次郎はどこへ行った...) console.log( ary ) ; /* 0: (2) ['源吉', '佐藤蛾次郎'] <-- 要素の値が変わってしまった。 1: (2) ['諏訪さくら', '倍賞千恵子'] 3: (2) ['タコ社長', '太宰久雄'] */ console.log( copyAry ) ; /* 0: (2) ['源吉', '佐藤蛾次郎'] 1: (2) ['諏訪さくら', '倍賞千恵子'] 3: (2) ['タコ社長', '太宰久雄'] */
JSON.parse(JSON.stringify()) で文字列に変換して複製
JSON.stringify() で配列を文字列に変換して、文字列を JSON.parse() を使って再び配列に変換するとディープコピー(深い複製)となります。
但し複製元の配列がJSONで表現可能でなければなりません。したがって要素内に undefined や関数オブジェクトなどが含まれていると複製できません。
let ary = [ [ '車寅次郎' , '渥美清' ] , [ '諏訪さくら' , '倍賞千恵子' ] , [ 'タコ社長' , '太宰久雄' ] , ] ; let copyAry = JSON.parse(JSON.stringify(ary)) ; // JSON で新しい配列を作成して複製 copyAry[0][0] = '源吉' ; // 複製先の要素を変更 copyAry[0][1] = '佐藤蛾次郎' ; // 複製先の要素を変更 // 複製元の要素の値は変わらない。 console.log( ary ) ; /* 0: (2) ['車寅次郎', '渥美清'] 1: (2) ['諏訪さくら', '倍賞千恵子'] 3: (2) ['タコ社長', '太宰久雄'] */ console.log( copyAry ) ; /* 0: (2) ['源吉', '佐藤蛾次郎'] 1: (2) ['諏訪さくら', '倍賞千恵子'] 3: (2) ['タコ社長', '太宰久雄'] */
JavaScriptにはディープコピーの方法が提供されていない。
JavaScriptではディープコピーの方法は提供されていないので、自作で実装する必要があります。
let ary = [ [ '車寅次郎' , '渥美清' ] , [ '諏訪さくら' , '倍賞千恵子' ] , [ 'タコ社長' , '太宰久雄' ] , ] ; /* 二次元配列の複製 ----------------------------------*/ function copyArray( arg ) { let resArg = [] ; for( const item of arg ) { resArg.push( Array.from( item ) ) ; } return resArg ; } let copyAry = copyArray(ary) ; // 自作の複製関数で新しい配列を作成して複製 copyAry[0][0] = '源吉' ; // 複製先の要素を変更 copyAry[0][1] = '佐藤蛾次郎' ; // 複製先の要素を変更 // 複製元の要素の値は変わらない。 console.log( ary ) ; /* 0: (2) ['車寅次郎', '渥美清'] 1: (2) ['諏訪さくら', '倍賞千恵子'] 3: (2) ['タコ社長', '太宰久雄'] */ console.log( copyAry ) ; /* 0: (2) ['源吉', '佐藤蛾次郎'] 1: (2) ['諏訪さくら', '倍賞千恵子'] 3: (2) ['タコ社長', '太宰久雄'] */
参考リンク
MDN 開発者向けのウェブ技術 > Array
MDN 開発者向けのウェブ技術 > concat
MDN 開発者向けのウェブ技術 > slice
MDN 開発者向けのウェブ技術 > スプレッド構文
MDN 開発者向けのウェブ技術 > Array.from
MDN 開発者向けのウェブ技術 > JSON.parse
MDN 開発者向けのウェブ技術 > JSON.stringify
MDN 開発者向けのウェブ技術 > JavaScript「再」入門