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