JavaScriptでは、オブジェクトが代入されている変数をほかの変数へ代入しても、オブジェクトはコピーされません(参照:変数へのオブジェクト代入は内容がコピーされるわけではない)。また、独自に作成した単純なオブジェクトは「new」演算子を使ってコピーすることができません。

 

以下の例は、ひな形のオブジェクトを使って簡単な「カード型データベース」を作成しようとして失敗しています。

//カード型データベースもどき(失敗例)

//カードのひな形 var profile= { firstName: "", familyName: "", age: undefined } var cards= []; //1枚目のカード cards[0]= new profile; //<-- エラー発生 cards[0].name= "1000p"; cards[0].familyName= "Nakatoji"; cards[0].age= 100; //2枚目のカード cards[1]= new profile; cards[1].name= "3p"; cards[1].familyName= "Hiratoji"; cards[1].age= 105;

上記の場合、1枚目のカードを作成するためにnew演算子を使用したところでエラーが発生します。エラーの内容は「オブジェクトにコンストラクタが存在しない」というものです。

「コンストラクタ」とは、「オブジェクトが自分自身を元に新しいオブジェクトを作成する関数」であり、それが存在しなければオブジェクトをコピーすることができません。

 

コンストラクタを継承したオブジェクトを作成するには、元になるオブジェクトを「関数」として作成するのが手っ取り早い方法で、以下のようにすれば、期待している目的は達成されます。

//カード型データベースもどき(オブジェクトの関数化)

//カードのひな形
function profile(){ this.name= ""; this.familyName= ""; this.age= undefined; } var cards= []; //1枚目のカード cards[0]= new profile(); //オブジェクトがコピーされる cards[0].name= "1000p"; cards[0].familyName= "Nakatoji"; cards[0].age= 100; cards[0].myOption= "alien"; //独自のプロパティを追加してみる //2枚目のカード cards[1]= new profile(); cards[1].name= "3p"; cards[1].familyName= "Hiratoji"; cards[1].age= 105; //テスト $.writeln (cards[0].name); //結果:"1000p" $.writeln (cards[1].name); //結果:"3p"
$.writeln (cards[0].myOption); //結果:"alien" $.writeln (cards[1].myOption); //結果:undefined(=影響されていない)

 

< さらにスマートなオブジェクトの複製方法 >

 

局所的にコピーを行いたい場合は上記のような方法で解決できますが、JavaScriptの流儀としては、このようなnew演算子の使用は推奨されていません。もし、うっかりnewを付け忘れた場合、元のオブジェクトを汚染する潜在的なリスクになるからです。

 

流儀に従ってそのようなリスクを嫌うなら、以下のように「オブジェクトを複製する関数」を作って回避する方法もあります。

//カード型データベースもどき(オブジェクトの関数化)

//オブジェクト複製用関数
function createObj(obj) {
	var f= function(){};
	f.prototype = obj.prototype;
	return new f;
}
//カードのひな形
var profile= { 
    firstName: "",
    familyName: "",
    age: undefined
}
var cards= [];
//1枚目のカード
cards[0]= createObj(profile); //ひな形からオブジェクトを生成1
cards[0].name= "1000p";
cards[0].familyName= "Nakatoji";
cards[0].age= 100;
cards[0].myOption= "alien"; //独自のプロパティを追加してみる
//2枚目のカード
cards[1]= createObj(profile); //ひな形からオブジェクトを生成2
cards[1].name= "3p";
cards[1].familyName= "Hiratoji";
cards[1].age= 105;
//テスト
$.writeln (cards[0].name); //結果:"1000p"
$.writeln (cards[1].name); //結果:"3p"
$.writeln (cards[0].myOption); //結果:"alien"
$.writeln (cards[1].myOption); //結果:undefined(=影響されていない)

 

 

Joomla templates by a4joomla