SlideShare a Scribd company logo
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({ … }); としたとき……

        def(“Ninja”)

    1. Ninja クラスを作成
    2. deferred.valueOf を設定
    3. deferred を返す                      def.js のコンテキスト内でグローバル

                       _super, _props を設定          deferred

       Person({ … });               def(“Ninja”) の返した deferred に valueOf が
                                    設定されているので……
1. deferred の _super に Person を設定
2. deferred の _props に { … } を設定

                                                deferred.valueOf

             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




               ご静聴ありがとうございました

More Related Content

defjs をひも解く

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