C++/Java/Pythonでクラスは使ってるしPythonではメタクラスも使うけど、JavaScriptのプロトタイプベースの継承ってのがよく分からん。prototypeプロパティ、prototype.constructorプロパティ、__proto__プロパティ、Object.createメソッド、new演算子なんかの挙動がこんがらがって。アレコレ実験して確かめたつもりになっても、あれ?これってプロパティが設定されているわけじゃなくてプロトタイプチェーンたどって呼び出されてるだけだった、なんてことが多くて。アホやな俺。
#1 JavaScriptにおける継承 とりあえず以下のようにやる。
var F = function(x){
this.x = x;
};
F.prototype.setX = function(x){
this.x = x;
};
F.prototype.getX = function(){
return this.x;
};
var f = new F(100);
var G = function(x){
F.call(this, x);
};
G.prototype = Object.create(F.prototype);
G.prototype.constructor = G;
var g = new G(100);
__proto__
は非標準なので使わない。Object.create
でプロトタイプを複製してprototype
プロパティに入れる。そのままだとnew G()
で生成されるインスタンスのコンストラクタがF
になってしまうので、G.prototype.constructor = G
する。
ここから下は、下書き。無視して。
#1 _proto_
__proto__
は隠されたプロパティで、プロトタイプチェーンはこのプロパティをたどって行われる。JavaScriptの実行エンジンによっては__proto__
プロパティが無いかもしれないが、とにかくすべてのオブジェクトには何らかの隠されたプロパティがあって、プロパティチェインのために使われる。名前がないと不便なので、__proto__
プロパティがあろうがなかろうがそう呼ぶ。任意のオブジェクトo
は__proto__
プロパティを持っていて、o
のプロパティp
を探すとき、p
が見つからなければo.__proto__.p
を探す。無ければo.__proto__.__proto__.p
を探すのだろう。で、jsdo.itで遊んでみたら、__proto__
はdeprecatedだから使うなって怒られた。http://jsdo.it/TakashiSasaki/wrD0 代わりにObject.getPrototypeOf
を使えってことらしい。
おお、拡張子を.mdにしたら自動的にMarkdownのマークアップを理解してそれっぽい表示にしてくれるのか。こりゃいいや。