Click here to load reader
Upload
masafumi-oyamada
View
2.790
Download
1
Embed Size (px)
Citation preview
def.js をひも解く~オレ標準 js 記法~
id:mooz
@stillpedant
自己紹介
• 名前
– mooz (Hatena, GitHub, …)
– stillpedant (Twitter, Google)
• 好きな言語
– Mozilla 系 JavaScript
• 作ったもの
– KeySnail (Emacs 版 Vimperator)
– MiSPLi (Lisp 処理系 in JavaScript)
– その他もろもろ
近影
詳しくは http://mooz.github.com/index-ja.html で
def.js
def.js
• http://github.com/tobeytailor/def.js
• Ruby に似た記法でクラス定義と継承が行える
サンプルコード
サンプルコード
!?
説明
• def (クラス名) (定義);
– クラス定義
– def ("Person") ({ … });
• def (クラス名) << 親クラス(定義);
– 親クラスを指定したクラス定義 (継承)
– def (“Ninja") << Person({ … });
• this._super();
– メソッド中から用いる
– 親クラスの同名メソッドを呼び出し
サンプルコード (再掲)
今回のスライドの目的
• def.js の挙動を理解する
• def (クラス名) (定義);
• def (クラス名) << 親クラス(定義);
• this._super();
def (クラス名) (定義);
def (クラス名) (定義);
• def 関数は関数 (deferred) を返す
• def(“Person”) とすると
– Person クラスが作成され (window.Person が定義される)
– 「定義 (props) を使って Person クラスを拡張する関数」が返る
• つまり def(“Person”)({ … }); とすると
– Person クラスが定義され, { … } を使ってそのクラスが拡張される
※ “拡張” : メソッドやプロパティを定義すること
def (クラス名) << 親クラス(定義);
def (クラス名) << 親クラス(定義);
• 前述の通り def 関数は関数 deferred を返す
• この関数には valueOf というプロパティが設定されている
• この valueOf がミソ
valueOf
• オブジェクトをプリミティブ値に変換する際に呼ばれる
• プリミティブ値が期待される場面にオブジェクトが出くわしたとき自動的に呼ばれる
valueOf の挙動
実行すると,
1. def(foo) called
2. def(bar) called
3. foo (valueOf)
4. bar (valueOf)
def (クラス名) << 親クラス(定義);
• def 関数は valueOf の設定された関数 deferred
を返す
• def (クラス名) << 親クラス(定義); とすると合計で 3 回関数が呼ばれる
def (クラス名)
親クラス(定義)
dererred.valueOf
(def の返り値)
def(“Ninja”) << Person({ … });
def(“Ninja”) << Person({ … }); としたとき……
deferred
def(“Ninja”)
1. Ninja クラスを作成2. deferred.valueOf を設定3. deferred を返す
Person({ … });
1. deferred の _super に Person を設定2. deferred の _props に { … } を設定
_super, _props を設定
deferred.valueOf
def(“Ninja”) の返した deferred に valueOf が設定されているので……
def.js のコンテキスト内でグローバル
1. deferred の _props を使い Ninja クラスを拡張2. deferred の _super を使い Ninja の親クラスを Person に設定
(Ninja に _superClass プロパティを設定する)
つまりは……
• A() 演算子 B() のとき
1. A()
2. B()
3. A の返したオブジェクトの valueOf
• という順番で呼ばれてくれれば何でも良い
• << である必要性は無い
– def(“Ninja”) >> Person({ … });
– def(“Ninja”) + Person({ … });
this._super();
_super();
• 関数の caller プロパティを使って _super の呼び出し元メソッドを取得.
• メソッドの _class プロパティによりクラスを取得
• クラスの _super プロパティにより親クラスを取得
• メソッドの _name プロパティによりメソッドの名前を取得し, 親クラスの持つ同名メソッドを呼ぶ
_super() の使う各プロパティ
• Klass.extend 時に追加– メソッドの _name
– メソッドの _class
• deferred.valueOf により追加
– クラスの _super
• JavaScript 標準
– arguments.callee• その関数自身
• JavaScript 非標準 (ほぼ全てのブラウザが実装)
– caller プロパティ• その関数を呼んだ関数
まとめ
まとめ
• def (クラス名) (定義);
– 関数を返す関数
• def (クラス名) << 親クラス(定義);
– valueOf
– << である必要なし
• this._super();
– arguments.callee.caller
演算子オーバーロード欲しい
資料
• def.js
– http://github.com/tobeytailor/def.js
• 日本語の解説コメントをつけたコード
– https://gist.github.com/2ac889f4b0276ddf9586
ご静聴ありがとうございました