prototype.js をできるだけ使わないために

ほぼ備忘録(略して『ほぼ備』)

オブジェクトの継承について考える。

※できるだけ、自然のままの JavaScript 構文を使えるように気をつけました…

ごちゃごちゃくっつけない。

ここ、個人的には重要だと思っております。


<ここから>


まずは Object クラスを汚染しる!(結局 object.js とか作ることに…) :

    Object.prototype.extend = function() {
        for (var i = 0; i < arguments.length; i++) {
            var base = new arguments[i]();
            for (property in base) {
                if (! this[property]) this[property] = base[property];
            }
        }
        return this;
    }

    Object.prototype.init = function() {
        // 引数がなくても動くように try
        try {
            this._constructor.apply(this, arguments[0]);
        } catch (e) {}
    }


うわー、初めから汚染してます、ごちゃごちゃくっつけております。

上記「 extend 」メソッドは prototype.js にも似たようなのが備わってるんですが気にしない(prototype 使う前からやってたし・・・)


あと、p(ry の extend のシンタックス

    Class.extend(Child, Parent); // 「子に」「親を」継承させる


(↑)がイヤだったので

    this.extend(Parent); // 「自分が」「親を」継承する


という感じで使えるように。


で、後はもう一つの「 init 」メソッドを使いつつ使用例:

    // 親クラス
    function Animal() {
        Animal.prototype._constructor = function(name) {
            this.name = name;
        }
        Animal.prototype.bark = function() {
            alert(this.name);
        }
        this.init(arguments);   
    }

    // 子クラス
    function Dog() {
        this.extend(Animal).init(arguments);
    }


親クラス、子クラスを定義して実行:

    var uma = new Animal('Stitch');

    uma.bark(); /* アラート「 Stitch 」 */

    var dog = new Dog('Snoopy');

    dog.bark(); /* アラート「 Snoopy 」 */


続いて、子クラスでメソッド追加。かつ親クラスのメソッドをオーバーライド:

    function Dog() {  
        Dog.prototype.run  = function() {
            alert("runs by " + this.speed + ".");
        }
        // コンストラクタをオーバーライド
        Dog.prototype._constructor = function(name, speed) {
            this.name  = name;
            this.speed = speed;
        }
        this.extend(Animal).init(arguments);    
    }


実行!:

    var dog = new Dog('Snoopy', '30Km/h'); // 引数を追加

    dog.bark(); /* アラート「 Snoopy 」*/

    dog.run();  /* アラート「 Runs by 30Km/h. 」*/


<ここまで>


function の中に Object.prototype を書くとクラスっぽく見えますね*1

*1:new の度に定義し直すので無駄は多いけど…