🍞
Javascriptでめっちゃ深いコピーする関数作ってみた
javascriptでオブジェクトとか連想配列なんかを深いコピーしたいときによく↓のやつ使ってたんですが、
javascript
/**
* lists:元の配列
* copy:コピー配列
*/
const copy = lists.map( list => ({...list}))
これだと下記のような深い階層のものだと、値が変わってしまうんですよね。
javascript
const lists = [{id:1, users:[{user_id:1},{user_id:2}]},{id:2, users:[{user_id:3},{user_id:4}]}];
const copy = lists.map( list => ({...list}))
copy[0].users[0].user_id = 20;
console.log(JSON.stringify(lists));
console.log(JSON.stringify(copy));
出力結果
javascript
[{"id":1,"users":[{"user_id":20},{"user_id":2}]},{"id":2,"users":[{"user_id":3},{"user_id":4}]}]
[{"id":1,"users":[{"user_id":20},{"user_id":2}]},{"id":2,"users":[{"user_id":3},{"user_id":4}]}]
そこでライブラリを使うなど、いろいろ方法はあるみたいです。
自作してみる
ただ、勉強がてら自分で作ってみようということで作ってみました。
それが↓
javascript
const associativeArrayCopy = (lists) => {
// オブジェクトかどうか判定する関数
const isObject = (value) => {
return value !== null && typeof value === 'object'
}
// 再帰的にコピーを返す関数
const entriesObject = (list) => {
// オブジェクトじゃなくて値になったら終了
if(!isObject(list)) return list;
// 再帰的にコピーする
return Object.entries(list).reduce((acc,[key, value]) => ({...acc, [key]:associativeArrayCopy(value)}), {});
}
// 配列かオブジェクトで分ける
return Array.isArray(lists) ? lists.map(list=> entriesObject(list)) : entriesObject(lists);
}
初めの方法を再帰的にやりました。試しに初めの深い階層のものでやってみます。
javascript
const lists = [{id:1, users:[{user_id:1},{user_id:2}]},{id:2, users:[{user_id:3},{user_id:4}]}];
const copy = associativeArrayCopy(lists)
copy[0].users[0].user_id = 20;
console.log(JSON.stringify(lists));
console.log(JSON.stringify(copy));
出力結果
javascript
[{"id":1,"users":[{"user_id":1},{"user_id":2}]},{"id":2,"users":[{"user_id":3},{"user_id":4}]}]
[{"id":1,"users":[{"user_id":20},{"user_id":2}]},{"id":2,"users":[{"user_id":3},{"user_id":4}]}]
間違ってたらごめんなさい。
参考サイト
Discussion