[Javascript] objectのディープコピーを便利に扱えるスニペット

2020年5月26日

Javascript テクノロジー プログラミング

特定の言語で、既存の機能に物足りなくなったら、自分のスキルが向上したことを感じる、ユゲタです。 javascriptのobjectディープコピーが度々話題になっていますが、jsonレベルのデータコピーは簡単にできるんですが、javascriptのobjectは、中にfunctionも含めて、複雑なデータが含まれているんですが、使用するケースがまあまあ多いことから、 簡単に使える関数とネイティブに使えるコードを記載しておきます。

本日のIT謎掛け

「データコピー」と、かけまして・・・ 「三部作の映画」と、ときます。 そのココロは・・・ サンショウ(参照と三章)が、全てにおいて重要になります。

ディープコピーの必要性

javascriptで、配列や連想配列などは、全てobjectというタイプに属します。 var objects = { a : "aa", b : "bb", c : function(){console.log("hoge")} }; var object_2 = JSON.parse(JSON.stringify(objects)); console.log(object_2); > {a: "aa", b: "bb"} そのobjectの中には、functionも含めることができるので、単純なjson構造では無くなる場合も多々あります。 このサイトでも過去に紹介した方法では、functionがコピーされません。 過去記事 : 【javascript】オブジェクトデータのコピー そして、何故ディープコピーをしなければ行けないかと言うと、 var objects = { a : "aa", b : "bb" }; var object2 = objects; object2.a = "cc"; console.log(objects); > {a: "cc", b: "bb"} このように、javascriptでobjectを別のobject変数に代入すると、参照コピーになってしまいます。

ディープコピー関数を紹介

参照コピーを便利に使える場面ではありがたいんですが、ちゃんとコピーしなければ、いけない場合も数多くあるので、以下のような関数を作ってみました。 $$deepcopy = (function(){ var MAIN = function(objects){ return this.deepcopy(objects); }; MAIN.prototype.deepcopy = function(objects){ if(objects === null || objects === undefined){return null;} var newObjects; switch(typeof objects){ case "undefined": case "string": case "number": case "function": newObjects = objects; break; case "object": newObjects = typeof objects.length !== "undefined" ? [] : {}; for(var i in objects){ newObjects[i] = this.deepcopy(objects[i]); } break; } return newObjects; }; return MAIN; })(); ディープコピーを使用する前に、この関数を実行して、読み込んでおきます。 var objects = { a : "aa", b : "bb", c : function(e){console.log("hoge")} }; var object2 = new $$deepcopy(objects); object2.a = "cc"; console.log(objects); > {a: "aa", b: "bb", c: ƒ} console.log(object2); > {a: "cc", b: "bb", c: ƒ} ちゃんと、データの変更がコピーされた側だけになっているのと、functionデータも一緒にコピーされていることが確認できました。

ネイティブ環境で使いたい

javascriptのObject関数として使うとnew宣言しなくても、objectに対して直接使うことができます。 まずは、使用したいWEBページで読み込んだ時に、以下のコードを実行しておきます。 if(typeof Object.prototype.deepcopy === "undefined"){ Object.prototype.deepcopy = function(objects){ if(objects === null || objects === undefined){return null;} var newObjects; switch(typeof objects){ case "undefined": case "string": case "number": case "function": newObjects = objects; break; case "object": newObjects = typeof objects.length !== "undefined" ? [] : {}; for(var i in objects){ newObjects[i] = this.deepcopy(objects[i]); } break; } return newObjects; }; } 使いたい時は以下のようにすると、簡単にデータのコピーをすることができます。 var objects = { a : "aa", b : "bb", c : function(e){console.log("hoge")} }; var obj2 = Object.deepcopy(objects); console.log(obj2); > {a: "aa", b: "bb", c: ƒ, deepcopy: ƒ} ちゃんとコピーできていることも確認できます。 手順としては、関数として登録するのと、ネイティブとして登録するのは、同じなのですが、ネイティブ関数は、他の機能なども含めて便利ライブラリにしておくと、javascriptのプログラム進行をする時に、スッキリとしたプログラムが構築できるようになります。 実は他にも溜め込んでいるネイティブ機能がたくさんあるので、そのうちに公開したいと思います。 もし、「こんな機能がほしい」というような要望などあれば、コメントもらえると嬉しいです!!!

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。