• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Web技術勉強会 20110528
 

Web技術勉強会 20110528

on

  • 1,177 views

プロトタイプベースOOPライブラリの紹介

プロトタイプベースOOPライブラリの紹介

Statistics

Views

Total Views
1,177
Views on SlideShare
1,176
Embed Views
1

Actions

Likes
0
Downloads
1
Comments
0

1 Embed 1

http://localhost 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Web技術勉強会 20110528 Web技術勉強会 20110528 Presentation Transcript

    • Web技術勉強会 2011/05/28 Ryuichi TANAKA/@mapserver2007/summer-lights.jp JavaScriptでプロトタイプベースオブジェクト指向プログラミング~続・親子関係を維持してクラスを使わないオブジェクト指向プログラミング手法~
    • 前回の内容簡単に継承var obj = Base.mix(Utils).mix(Http); mixメソッドで簡単にモジュールをMix-in親子関係を維持した継承obj.parent().getName(); 子と親で同じメソッドがあった場合、従来の継承では上書きされ てしまうため親メソッドにアクセス不能だったが、parent()経由 でアクセス可能にした
    • 今回の目的前回の問題点の解消 Object拡張によるprototype汚染問題 for-inに拡張したプロパティが含まれる問題 実装の致命的ミス(あとで発覚)IE対応 IEにはプロトタイプチェーンがないのでメソッドのチェーン探索 ができない問題 __proto__がないので親を辿れない問題前回の残課題 多重継承機能未実装新たな課題 Mix-in、多重継承したオブジェクトを再継承する機能テスト 自動テストで正しく動くかどうか確認する公開 正式公開(ライセンスを付与して使えるようにする)
    • 前回の問題点①prototype汚染問題起こる実害 オブジェクトを作ると必ず追加したメソッドmix, parent が付随してきてしまう これによりmix, parentが予約させるためライブラリ使用 者が再定義不能、for-inループ時にmix, parentが出現す る問題が発生する var obj = {}; // = new Object(); for (var prop in obj) { alert(prop); // mix, parent }
    • 前回の問題点①prototype汚染はやはり避けるべきである汎用性を求めない、プロジェクトの一部でしか使わないなど、範囲がごく狭い場合ではあるいは許容してもいいかもしれないが、一般的には避けるべき。 当初、狭い範囲のライブラリの扱いだったが、急遽汎用 性を求めるように方向転換したため変更の必要が出た。for-inに含まれるのがあまりに大きい。回避も可能だが、毎回Object#hasOwnPropertyでチェックしないといけない。hasOwnPropertyの存在を知らない人が使ったら100%バグになる。 これは無視できない問題。この問題がある以上 prototype汚染は避けないと後々つらいことになる。
    • 前回の問題点①実は前回の内容には決定的なバグが存在していた これはひどい。先週時点では糞ライブラリと言われても 反論できないです…。mixi-inで「オブジェクト自体」を拡張していたつまり…var obj = Iphone.mix(Feature).mix(Telephone);alert(obj.parent().getPhoneName()); // garake-var obj2 = Iphone; // 継承しないalert(obj2.parent().getPhoneName()); // garake- \(^o^)/もとのオブジェクト(Iphone)が勝手に拡張されるため、Mix-in後に単独で使ったりするとおかしなことになる。
    • 前回の問題点①を解決mix, parentメソッドを動的に追加するモジュールを一つ定義するように変更。このモジュールを経由してオブジェクトを生成するルールとする。Objectを拡張しないので{}.mix(), {}.parent()は実行できない=for-in問題も解決。var Module = {};Module.create = function() { // …};
    • 前回の問題点①を解決オブジェクト自体を拡張しないようにする ここで言うオブジェクトとは、Objectのことではなく利 用者が定義したモジュールオブジェクトのことJavaScriptは参照渡しが基本 そのままオブジェクト(this)を拡張するともとのオブジェ クトにも影響が出てしまうJavaScriptにはディープコピーがない var copy = origin; とやってもシャローコピーになる copyを拡張するとoriginも拡張される var copy = clone(origin); のようにディープコピーする 処理を実装してあげることで解決する
    • 前回の問題点①を解決var Iphone = Module.create({ getPhoneName: function() { return “iphone”; }});// alert(Iphone.hasOwnProperty(“mix”)); // true// alert(Iphone.hasOwnProperty(“parent”); // true// Feature, Telephoneも同様に定義var obj = Iphone.mix(Feature).mix(Telephone);alert(obj.parent().getPhoneName()); // garake-var obj2 = Iphone;alert(obj2.parent().getPhoneName()); // undefined method
    • 前回の問題点②IE未対応 趣味なら問題ない(公開してるシステムはほとんどIE未対 応) だが、個人的な野望として仕事で使いたいと密かに思っ てるのでこれはなんとかしたい。 仕事ではIEだらけ。避けて通れない…。 ライセンスさえクリア出来れば仕事でも使える。とはいえ簡単じゃない モダンブラウザでできた__proto__による継承関係、プ ロトタイプチェーンを利用した親のメソッド自動探索が 使えない。つまりこれを自前で作らないといけない。この問題が今回の最難関
    • 前回の問題点②を解決__proto__を使わないで動的に親子関係を構築する以下のパターン全てに対応する(パターンが多いので一部省略、テストでは全部実施)単独Mix-inパターン Iphone.mix(Feature)単独Mix-in連鎖パターン Iphone.mix(Feature).mix(Telephone)多重継承パターン Iphone.mix(Feature, Telephone)多重継承連鎖パターン Iphone.mix(Fetature, Telephone).mix(Android, Ipad)
    • 単独Mix-inオブジェクトを親にしたMix-inパターン var obj = Iphone.mix(Feature) obj.mix(Telephone)単独Mix-inオブジェクトを子にした多重継承パターン var obj = Iphone.mix(Feature) Telephone.mix(obj, Android)多重継承オブジェクトを親にしたMix-inパターン var obj = Iphone.mix(Feature, Telephone) obj.mix(Android)多重継承オブジェクトを子にした多重継承パターン var obj = Iphone.mix(Feature, Telephone) Android.mix(obj, Ipad)
    • 実装方法について(__proto__の代用)Iphone.mix(Feature).mix(Telephone) ② オブジェクト探索は Iphone プロトタイプチェーンをと同じこと。 ① Feature 探索処理を自前で実装した。 parent() ③ getPhone parent() Telephone Name() getPhone Name() parent() getPhone Name()①:子(Iphone#parent)は親(Feature)オブジェクトを指すようにする②:①で一つのオブジェクトとして扱う③:②のオブジェクト(parentの指す先を探し続ける)を探索して一番親のオブジェクト(Feature#parent)を見つけて、その親(Telephone)を指すようにする
    • 実装方法について(プロトタイプチェーンの代用)var obj = Iphone.mix(Feature).mix(Telephone)obj.getType() // Telephone#getType obj Iphone Feature ④ parent() parent() ③ parent() getPhone getPhone ① Name() getPhone Name() Telephone Name() getType() getType() getType() parent() getPhone Name() ② getType()①:objにコピーする②:子は親(祖先)を辿り、子にないメソッドがあればobjにコピーする。かつ、親はその親(祖先)を辿り、親にないメソッドがあれば親にコピーする。③:親を辿り、すでに子にコピー済みのメソッドであればコピーしない④:parent()はコピーしない(mix()も同様)
    • 実装方法について(プロトタイプチェーンの代用)子に親以上(祖先すべて)のメソッドをコピーする理由 プロトタイプチェーンで辿れないのですべて子にコピーする こうすることで、呼び出し方はモダンブラウザと同じになる (内部処理は異なる)祖先にしか存在しないメソッドを子にコピーしているので若干効率が悪い IEではこうするしかないと判断(もっと良いやり方があれば…) IEは割り切るしかないかな、と。現状ではIEとその他ブラウザで同じ動作をするようにまでなったのでひとまずよしとした。
    • 前回未実装機能を実装多重継承 obj = Iphone.mix(Feature, Telephone);実装自体は非常に簡単に完了 引数を可変にするだけ。arguments.length回同じことをする だけ。
    • Mix-in、多重継承したオブジェクトを再継承する機能Mix-inしたオブジェクトを継承対象にする obj = Iphone.mix(Feature).mix(Telephone); obj2 = Android.mix(obj); obj3 = obj2.mix(Ipad)多重継承したオブジェクトを継承対象にする obj = Iphone.mix(Feature, Telephone); obj2 = Android.mix(obj, Ipad); obj3 = obj.mix(Android, Ipad);既存の継承機能を少し拡張することで対応。そんなに難しくなかった。
    • テストQUnit jQueryのテスト用フレームワーク。現在はjQuery非依存のjs でもテスト可能。 xUnitが分かればすぐ使える ローカルに落としてきて、test/index.htmlを実行するだけhttps://gist.github.com/982540 21項目、61個のテストを作成 IE8,Chrome11ですべてパスを確認
    • 公開についてhttps://github.com/mapserver2007/mixjs 圧縮版も合わせて付属させる予定 オプションとしてモジュールもCommitする予定
    • 主要JavaScriptライブラリとの比較 jQuery prototype.js Ext.js mix.js継承方法 プロパティ クラスベース クラスベース プロトタイプベース 上書き親子関係 ☓ ☓ ☓ ○の維持親の呼び 呼び出し不 Super.prototyp Super.supercla obj.parent().getNa出し方 可 e.getName.appl ss.getName.ap me() y(this) ply(this, arguments)継承の仕 var obj = var obj = var obj = var obj =方 $.extend(o Object.extend(c Ext.extend(cls1, o1.mix(o2) 1, o2) ls1, cls2) cls2)メリット シンプル 馴染みある継承 馴染みある継承 シンプル 方法 方法デメリッ 親を呼び出 親の呼び出し方 親の呼び出し方 オブジェクトにmix,ト すことが出 が長い が長い parentが実装される 来ない
    • まとめ前回作成したコードをBrushUp バグはほぼない状態 IE対応まずは今つくっているシステムに導入する予定問題なさそうなら仕事でも使いたい