2018-1-1
[JS] シャローコピーとディープコピー
結論
ディープコピーしたいならlodash
のcloneDeep
を使え。
シャローコピーとディープコピー
- シャローコピー:参照を維持しているコピー
- ディープコピー:参照を切ったコピー
シャローコピーの方法
普通に代入すれば良い
var original = [0, 1, 2];
var copy = original;
copy[0] = 3;
console.log(copy); // => [ 3, 1, 2 ]
console.log(original); // => [ 3, 1, 2 ]
ディープコピーの方法
こちらは一筋縄では行かない。
結論から言うと、lodash
のcloneDeep
を使うのが一番。
Object.assign
の問題
Object.assign
はディープコピーする方法としてよく紹介されているがディープコピされるのは1階層目だけで、2階層目以降は普通にシャローコピーされる。
var original = {
name: 'article name',
date: {
created: '20171201',
updated: '20171202',
},
};
var copy = Object.assign({}, original);
copy.name = "copy article";
copy.date.updated = '20180101';
console.log(copy);
console.log(original);
出力はこう
{ name: 'copy article',
date: { created: '20171201', updated: '20180101' } }
{ name: 'article name',
date: { created: '20171201', updated: '20180101' } }
単純なオブジェクト等では問題なくディープコピーされるため、問題なく使えそうに見えやすく逆にハマってしまうとやばそう。
JSON.parse/stringify
の問題
こちらも JS によるディープコピーの方法としてよく紹介されている。
こちらはプロパティに function や undefined があると、そのプロパティ自体が消えてしまう問題がある。(JSON.stringify するのだから当然といえば当然)
var original = {
count: 0,
countUp: function() {
this.count++;
},
countDown: function() {
this.count--;
},
};
var copy = JSON.parse(JSON.stringify(original));
copy.countUp(); // error
というわけでlodash
を使おう。
参考
ES6 の Object.assign がシャローコピーなのでディープコピーする方法を考える | Black Everyday Company