JavaScript言語では、オブジェクトのプロパティを探索する際に、まずオブジェクトが直接持っているプロパティから、該当のプロパティを探索します。そこになかった場合、オブジェクトのクラス(JavaScriptの場合、厳密にはコンストラクタ)のprototypeプロパティの中から、該当する名前のプロパティを探します。
たしかこの辺りを鵜呑みにしていたと思う。
function C(){}
var c = new C;
C.prototype = { x: 'x' };
c.x; // undefined
ほら。C.prototypeは見ていないよ。
function C(){}
var c = new C;
C.prototype.x = 'x';
c.x; // 'x'
C.prototype はただの参照。
詳しく書いた。agenda(Weblog)プロトタイプチェインについての覚書(ECMAScript, JavaScript)
話題は逸れるけれど今使っている擬似継承用のメソッド:
Function.prototype.inherit = function(superClass) {
/* http://www.skipup.com/~peace/javascript/ */
function Temp(){}
Temp.prototype = superClass.prototype;
this.prototype = new Temp;
this.prototype.__super__ = superClass;
this.prototype.constructor = this; };
これは本当はこうしたい。
Function.prototype.inherit = function(superClass) {
this.prototype.__proto__ = superClass.prototype;
this.prototype.__super__ = superClass; };
Tempなる空っぽのコンストラクタを呼び出したり、消してしまったconstructorプロパティを再設定するのを防げるし、何よりプロトタイプチェインが「見える」。
これらとECMAScript仕様書をあわせ読みつつ、ようやくJavaScriptのプロトタイプチェインが理解できた気がする。というか__proto__で分かった。コンストラクタのprototypeプロパティなんか参照しないじゃあないか(ユーザー定義の場合は new するとき以外)。これが数々の誤解を生んでいたと思うと 。