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

2020年5月26日

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

t f B! P L
特定の言語で、既存の機能に物足りなくなったら、自分のスキルが向上したことを感じる、ユゲタです。 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のプログラム進行をする時に、スッキリとしたプログラムが構築できるようになります。 実は他にも溜め込んでいるネイティブ機能がたくさんあるので、そのうちに公開したいと思います。 もし、「こんな機能がほしい」というような要望などあれば、コメントもらえると嬉しいです!!!

このブログを検索

プロフィール

自分の写真
プログラミングとサーバーを心の底から楽しむクリエーターです。 経営者であり、開発者でもありますが、得意としているのは、アイデア創出で、出来高は無限大です。

ブログ アーカイブ

QooQ