JavaScript(ES6/ES2015)でオブジェクトをコピーする時に注意すること
どうも、はぐっです・ω・♪
今回は、
「JavaScript(ES6/ES2015)でオブジェクトをコピー」
を実現させるのですが、その際の注意点を。
もう、babelを利用してES6/ES2015でJavaScriptを書いている人もだいぶ増えて来たことかと思います。 で、様々な場面でオブジェクトを扱うことが多くあるはずっ。
んで、コピーしたいなんてこともあるはずっ。
そんなとき、コピーの仕方はいくつかあると思いますが、ここでは二つのやり方を。
jQueryを利用してオブジェクトをコピー
JavaScript界の大ベテラン、「jQuery」
こいつに、オブジェクトをコピーする時に使えるメソッドが用意されています。
(本来の目的はオブジェクトのマージだったり。)
$.extend
使い方は
let firstObj = { a: 'a', b: { a: 'a', b: { a: 'a' } } }; let secondObj = $.extend(true, {}, firstObj);
はいっ、こぴー。
第一引数: ディープコピーかどうか(省略可) 第二引数: マージのもととなるオブジェクト 第三引数以降: マージするオブジェクト(いくつでも)
ん?
ディープコピー?
そう! 今回はここがポイントです!
ディープコピーとは
まぁ、「とは」っていうほど定義が必要なものではなくて、
deep:深い
つまり、深いコピーをするか、浅いコピーをするか。 下の階層まで再帰的にコピーするか。
ここ、割と大事。
ES6/ES2015を利用してオブジェクトをコピー
ES6/ES2015になって、 待ってましたー!!!!
な機能が様々追加され、いろいろとはっぴーになったわけですが、
その中の一つ。
Object.assign
こいつ。
使い方は
let firstObj = { a: 'a', b: { a: 'a', b: { a: 'a' } } }; let secondObj = Object.assign({}, firstObj);
はいっ、こぴー。
第一引数: マージのもととなるオブジェクト 第二引数以降: マージするオブジェクト(いくつでも)
うむ。 さっきのjQueryのextendと使い方自体はそうかわら・・・
ディープは!?
そう、ここが違うのです。
Object.assignは、シャローコピー(ディープコピーと違って浅いコピー)なのです!!
これね、困る時があるんですよ。
コピーのやり方による違い
例えば
let firstObj = { a: 'a', b: { a: 'a', b: { a: 'a' } } };
があったとしてですよ。
$.extendの場合
let secondObj = $.extend(true, {}, firstObj); secondObj.b.a = 2; console.log(firstObj.b.a); // 1 console.log(secondObj.b.a); // 2
この場合、出力は
1: a 2: 2
となります。
Object.assignの場合
let secondObj = Object.assign({}, firstObj); secondObj.b.a = 2; console.log(firstObj.b.a); // 1 console.log(secondObj.b.a); // 2
この場合、出力は
1: 2 2: 2
となります。
ほらああああああああああ!!!
こういうところで違いがでてくるんですよ!
だから言ったじゃないですかあああ!
…こほん。
つまりね、
オブジェクトがプロパティとしてオブジェクトを持っている時、
シャローコピー(Object.assign)だと同じ参照
ディープコピー($.extend(true))だと別参照
となるわけですね。
みなさま、くれぐれもオブジェクトのコピーは慎重に。
ES6/ES2015のご利用は計画的に。