SlideShare una empresa de Scribd logo
1 de 21
Descargar para leer sin conexión
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対応
まずは今つくっているシステムに導入する予定
問題なさそうなら仕事でも使いたい

Más contenido relacionado

Más de 龍一 田中

Web技術勉強会 20111112
Web技術勉強会 20111112Web技術勉強会 20111112
Web技術勉強会 20111112
龍一 田中
 
Web技術勉強会 20100925
Web技術勉強会 20100925Web技術勉強会 20100925
Web技術勉強会 20100925
龍一 田中
 

Más de 龍一 田中 (20)

WebSocketでリアルタイム処理をする
WebSocketでリアルタイム処理をするWebSocketでリアルタイム処理をする
WebSocketでリアルタイム処理をする
 
Web技術勉強会 20130525 - Google Cloud Messaging入門
Web技術勉強会 20130525 - Google Cloud Messaging入門Web技術勉強会 20130525 - Google Cloud Messaging入門
Web技術勉強会 20130525 - Google Cloud Messaging入門
 
Web技術勉強会 20120728
Web技術勉強会 20120728Web技術勉強会 20120728
Web技術勉強会 20120728
 
Web技術勉強会 20120609
Web技術勉強会 20120609Web技術勉強会 20120609
Web技術勉強会 20120609
 
Web技術勉強会 20120114 - JenkinsでJava/PHP/Ruby/JavaScriptをビルドする
Web技術勉強会 20120114 - JenkinsでJava/PHP/Ruby/JavaScriptをビルドするWeb技術勉強会 20120114 - JenkinsでJava/PHP/Ruby/JavaScriptをビルドする
Web技術勉強会 20120114 - JenkinsでJava/PHP/Ruby/JavaScriptをビルドする
 
Web技術勉強会 20111112
Web技術勉強会 20111112Web技術勉強会 20111112
Web技術勉強会 20111112
 
Web技術勉強会 20110611
Web技術勉強会 20110611Web技術勉強会 20110611
Web技術勉強会 20110611
 
Web技術勉強会 20100925
Web技術勉強会 20100925Web技術勉強会 20100925
Web技術勉強会 20100925
 
Web技術勉強会 20100424
Web技術勉強会 20100424Web技術勉強会 20100424
Web技術勉強会 20100424
 
Web技術勉強会 第38回
Web技術勉強会 第38回Web技術勉強会 第38回
Web技術勉強会 第38回
 
Web技術勉強会 第37回
Web技術勉強会 第37回Web技術勉強会 第37回
Web技術勉強会 第37回
 
Web技術勉強会 第34回
Web技術勉強会 第34回Web技術勉強会 第34回
Web技術勉強会 第34回
 
Web技術勉強会 第33回
Web技術勉強会 第33回Web技術勉強会 第33回
Web技術勉強会 第33回
 
Web技術勉強会 第31回
Web技術勉強会 第31回Web技術勉強会 第31回
Web技術勉強会 第31回
 
Web技術勉強会 第30回
Web技術勉強会 第30回Web技術勉強会 第30回
Web技術勉強会 第30回
 
Web技術勉強会 第29回
Web技術勉強会 第29回Web技術勉強会 第29回
Web技術勉強会 第29回
 
Web技術勉強会 第28回
Web技術勉強会 第28回Web技術勉強会 第28回
Web技術勉強会 第28回
 
Web技術勉強会 第26回
Web技術勉強会 第26回Web技術勉強会 第26回
Web技術勉強会 第26回
 
Web技術勉強会 第25回
Web技術勉強会 第25回Web技術勉強会 第25回
Web技術勉強会 第25回
 
Web技術勉強会23回目
Web技術勉強会23回目Web技術勉強会23回目
Web技術勉強会23回目
 

Último

Último (7)

Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 

Web技術勉強会 20110528