- 2009年3 月31日(火)
- 未分類
どうも。shimazakiです。
javascriptでprototypeプロパティについてアレコレしていたら自分が大きく誤解をしていたことを理解しましたので、ついでに紹介したいと思います
以下の結果がどうなるか、って分かりますか?
Hoge.prototype = {
aList:["123"]
,xList:["456"]
};
foo = new Hoge();
foo.aList = ["789"];
foo.xList.push("789");
alert(foo.aList);//789
alert(foo.xList);//456,789
bar = new Hoge();
alert(bar.aList);//???
alert(bar.xList);//???
正解はbar.aListは「123」 bar.bListは「456,789」と表示されます。
何を勘違いしていたか?
- prototypeはreadOnlyという誤解
解説書などに見る「暗黙の参照」と言う言葉、読み込み時のみ評価されるという説明で、prototypeプロパティはインスタンスからは書き換えが出来ないと思っていました。
したがって、プロパティの継承が有効なのは、プロパティの値を書き込むときではなく、読み出すときに限られます。プロトタイプからプロパティを継承するオブジェクトoにプロパティpを設定すると、新しいプロパティpが生成され、オブジェクトoに直接格納されます。(JavaScript第5版 P155 9.2 プロトタイプと継承)
「書き換えが出来る」ってわけではない
Hoge.prototype = {
aNum:1
,xNum:10
};
foo = new Hoge();
foo.aNum = 2;
foo.xNum++;
alert(foo.aNum);//2
alert(foo.xNum);//11
bar = new Hoge();
alert(bar.aNum);//??
alert(bar.xNum);//??
とした場合、aNumは「1」、xNumは「10」です。
直接値を操作しようとしている(xNum++)のに値はprototypeのままです。
つまり、prototypeプロパティのプロパティでプリミティブ値ではないものは参照渡ししてるってこと?
Hoge.prototype = {
aObject:{a:"a"}
,xObject:{}
};
foo = new Hoge();
foo.aObject.a="aa";
foo.xObject.x="x";
alert(foo.aObject.a);//aa
alert(foo.xObject.x);//x
bar = new Hoge();
alert(bar.aObject.a);//aa
alert(bar.xObject.x);//x
やっぱり。
prototypeのプロパティがプリミティブ値かどうかで判断しているっぽい。かな。
コピーはされてるのか?
Hoge.prototype = {
aNum:1
,xList:[]
};
foo = new Hoge();
foo.aNum++;
foo.xList.push("123");
alert( foo.hasOwnProperty("aNum") ); // true
alert( foo.hasOwnProperty("xList") ); // false
コピーされていない!
結局どういうことかというと、
- prototypeプロパティのプロパティがプリミティブ値であった場合、プロパティのコピーが行われ、処理は元オブジェクトに対してのみ行われる
- prototypeプロパティがプリミティブ値でなかった場合、プロパティのコピーが行われず、処理はprototypeプロパティに対してのみ行われる。
JavaScriptはまだまだ奥が深いです。
- Newer: TCPDFを使ってみる
- Older: JavaScriptでオブジェクト指向