« タグラインとは | トップページ | sbm4clg.js version 0.2 »

2007/04/21

プロトタイプチェーンの図とか

自分用に図を描いてみた。JavaScript のプロトタイプチェーン。たぶんきっとこんな感じかなと。

プロトタイプチェーン

[追記 at 2008/04/30]
constructor プロパティも書き加えた、より汎用的な図はこちらで。
[/追記]

で、これは以下のコードを基に図に起こしたもの。いろんなサイトを巡って勉強するのももちろんだけど、やっぱり自分でコード書かないと身に付かないなぁとしみじみ思ったり。

ちなみに、__proto__ プロパティは基本的には内部プロパティであり、一部のホスト環境でしかアクセスできないのでご注意を。Firefox では動きます。

//画面表示関数
function debugPrint() {
  var separator = " ";
  alert(Array.prototype.join.apply(arguments, [separator]));
};



/**
 * Object <- Worker <- PartTimer <- Cook
 *                               <- Waiter
 */

/**
 * 労働者オブジェクト
 */
function Worker() {}
Worker.prototype = {
  workedTime: 0,
  getMonthlyPay: function() {}
};

/**
 * アルバイト オブジェクト
 */
function PartTimer() {}
PartTimer.prototype = new Worker();
PartTimer.prototype.hourlyPay = 800;
PartTimer.prototype.getMonthlyPay = function() {
  return this.hourlyPay * this.workedTime;
};

/**
 * 調理係オブジェクト
 */
function Cook() {}
Cook.prototype = new PartTimer();
Cook.prototype.advantage = 50;
Cook.prototype.getMonthlyPay = function() {
  return (this.hourlyPay + this.advantage)
    * this.workedTime;
};

/**
 * 接客係オブジェクト
 */
function Waiter() {}
Waiter.prototype = new PartTimer();

//プロトタイプ チェーン
(function() {
  var c = new Cook();
  
  //その1
  debugPrint("Chain1:",
    (c.__proto__ === Cook.prototype),
    (c.__proto__.__proto__ === PartTimer.prototype),
    (c.__proto__.__proto__.__proto__ === Worker.prototype),
    (c.__proto__.__proto__.__proto__.__proto__
        === Object.prototype),
    (c.__proto__.__proto__.__proto__.__proto__.__proto__
        === null));
  
  //その2
  debugPrint("Chain2:",
    (c.__proto__ === Cook.prototype),
    (Cook.prototype.__proto__ === PartTimer.prototype),
    (PartTimer.prototype.__proto__ === Worker.prototype),
    (Worker.prototype.__proto__ === Object.prototype),
    (Object.prototype.__proto__ === null));
  
  //その3
  debugPrint("Chain3:",
    (Waiter.prototype.__proto__ === PartTimer.prototype),
    (Cook.prototype.__proto__ === PartTimer.prototype),
    (Waiter.prototype.__proto__ === Cook.prototype.__proto__));
})();

//プロパティ探索
(function() {
  var c = new Cook();
  c.cook = function() { return "Good taste!" };
  
  debugPrint("cook:",
    c.hasOwnProperty("cook"));
  
  debugPrint("advantage:",
    c.hasOwnProperty("advantage"),
    c.__proto__.hasOwnProperty("advantage"));
  
  debugPrint("hourlyPay:",
    c.hasOwnProperty("hourlyPay"),
    c.__proto__.hasOwnProperty("hourlyPay"),
    c.__proto__.__proto__.hasOwnProperty("hourlyPay"));
  
  debugPrint("workedTime:",
    c.hasOwnProperty("workedTime"),
    c.__proto__.hasOwnProperty("workedTime"),
    c.__proto__.__proto__.hasOwnProperty("workedTime"),
    c.__proto__.__proto__.__proto__.hasOwnProperty(
        "workedTime"));
  
  debugPrint("getMonthlyPay:",
    c.hasOwnProperty("getMonthlyPay"),
    c.__proto__.hasOwnProperty("getMonthlyPay"));
    
//[return] true
//  c.__proto__.__proto__.hasOwnProperty("getMonthlyPay");
//  c.__proto__.__proto__.__proto__.hasOwnProperty(
//    "getMonthlyPay");
  
//[warning] reference to undefined property
//  c.hoge;
})();



/**
 * 労働者 P オブジェクト
 * prototype で workedTime を定義
 */
function WorkerP() {}
WorkerP.prototype = {
  workedTime: 0
};

/**
 * 労働者 C オブジェクト
 * コンストラクタで workedTime を定義
 */
function WorkerC() {
  this.workedTime = 0;
}
WorkerC.prototype = {};

/**
 * 労働者 W オブジェクト
 * prototype で workedTime を定義してコンストラクタから使用
 */
function WorkerW() {
  this.workedTime = 0;
}
WorkerW.prototype = {
  workedTime: null
};

//オブジェクトのプロパティ探索
(function() {
  debugPrint("FunctionObject:",
    WorkerP.prototype.hasOwnProperty("workedTime"),
    WorkerW.prototype.hasOwnProperty("workedTime"));
  
//[return] false
//  WorkerP.hasOwnProperty("workedTime");
//  WorkerP.__proto__.hasOwnProperty("workedTime");
//  WorkerC.hasOwnProperty("workedTime");
//  WorkerC.prototype.hasOwnProperty("workedTime");
//  WorkerC.__proto__.hasOwnProperty("workedTime");
//  WorkerW.hasOwnProperty("workedTime");
//  WorkerW.__proto__.hasOwnProperty("workedTime");
})();

//インスタンスのプロパティ探索
(function() {
  var p = new WorkerP();
  var c = new WorkerC();
  var w = new WorkerW();
  
  debugPrint("Instanse:",
    p.__proto__.hasOwnProperty("workedTime"),
    c.hasOwnProperty("workedTime"),
    w.hasOwnProperty("workedTime"),
    w.__proto__.hasOwnProperty("workedTime"));

//[warning] reference to undefined property
//[Error] has no properties
//  p.prototype.hasOwnProperty("workedTime");
//  c.prototype.hasOwnProperty("workedTime");
//  w.prototype.hasOwnProperty("workedTime");

//[return] false
//  p.hasOwnProperty("workedTime");
//  c.__proto__.hasOwnProperty("workedTime");
})();

|

« タグラインとは | トップページ | sbm4clg.js version 0.2 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/253814/6166902

この記事へのトラックバック一覧です: プロトタイプチェーンの図とか:

« タグラインとは | トップページ | sbm4clg.js version 0.2 »