prototypeとスピリチュアル

この前,諸事情でこんなプログラム書いたんよね.

// 最近のブラウザはObject.createは結構実装されてるみたいだよ!(調べろ)
if(typeof Object.create !== "function") {
  Object.create = function(o) {
    function F() {}
    F.prototype = o;
    return new F();
  };
}

var caluculater = {
  count: 0,
  calc: function(n) {
    this.count += n;
  }
};

var c1 = Object.create(caluculater);
console.log(c1.count); // 0
c1.calc(3);
console.log(c1.count); // 3

var c2 = Object.create(caluculater);
console.log(c2.count); // 0
c2.calc(2);
console.log(c2.count); // 2

ここまで書いて実行して,あれってなった.
c1もc2もprototypeとして同じオブジェクトを共有してるんだからcountの値ってクラス変数みたいに共有するんじゃないの?
で, 色々調べてみました.

結論からいうとオブジェクト生成直後はprototypeのcountプロパティ,calcメソッド呼び出し後は,それぞれのオブジェクトのcountプロパティを出力している.
生成直後のオブジェクトは生まれたばかりの赤ん坊のようなもので,なにも知らない.現になにもプロパティを持っていない.分からないことがあったら守護霊(prototypeであるcaluculaterオブジェクト)に聞くしかない.

スピリチュアルな部分

おいおい・・・c1,c2って同じ守護霊なのか.普通,守護霊って一人につき一体じゃないのか?とツッコミたいところだが,昔読んだ怪しい本によると守護霊は複数人に憑くらしい(注:僕は怪しい宗教にハマってないよ!).あと一人に何体も守護霊が憑くらしい.そこまで考えるとJavaScriptの世界だと面倒くさいからやめよう(多重継承).

だれか「ねぇ,c1,countプロパティの値を教えてよ」
c1「僕,生まれたばかりだから知らな・・・」
守護霊(caluculater)「(c1よ, それは0ですよ)」
c1「あ,やっぱり知ってた. 0だよ,0.」

と,生まれたばかりのときはなにも知らないc1だけど,成長してマセてくると(calcメソッドを呼ぶと)自分自身でcountプロパティを持つようになる.
ポイントはcalcメソッドの

//this.count += n;
this.count = this.count + n;

の部分.
c1がcalcメソッドが最初に呼んだとき,thisは当然c1,countプロパティを参照しようとする(右項のやつ)と生まれたばかりだから守護霊に聞く.その後の再代入でc1自身がcountプロパティを持つようになる(左項のやつ).
というわけで,初期値としては共有しているけど,計算した後は別々のプロパティになるのでした.

てか,初期値をprototypeで定めている書き方がマズいともいえる・・・