自分用class定義ライブラリmyclass.jsを作ってみる(4)

改定版 myclass.js

前回の$super問題を解決したmyclass.jsの改定版です。ちなみにオリジナルはこちらです。

(function(){
    window.MyClass = {
        create : function(c,e){
            var f = function(){
                var ins;
                return (ins=MyClass.getMyInstance(f)).init.apply(ins,arguments);
            }
            f.__member__ = e||c;
            if(e)e.__c__=c;
            return f;
        },
        getMyInstance : function(f){
            var util = MyClass.MyUtil;
            if (f.__member__.__c__) {
                var ins = MyClass.getMyInstance(f.__member__.__c__)
                var $super = ins;
                ins = util.extend(
                        util.getInstance($super),util.getInstance(f.__member__,true)
                );
                ins.$super = $super;
                ins.MyUtil=util;
                return ins;
            }
            return util.getInstance(f.__member__||f,true);
        }
    }
    window.MyClass.MyUtil = {
        extend : function(obj,ext){
            for(var i in ext)obj[i]=ext[i];
            return obj;
        },
        getDeepInstance : function(obj){
            if (obj.constructor === Object) {
                var f = function(){};      
                for(var i in obj)f.prototype[i]=MyClass.MyUtil.getDeepInstance(obj[i]);
                return new f();
            }
            else return obj;
        },
        getInstance : function(obj,deep){
            var f;
            (f = function(){}).prototype = obj;      
            obj = new f;
            if(deep)for(var i in obj)obj[i]=MyClass.MyUtil.getDeepInstance(obj[i]);
            return obj;
        }
    }
})();

オリジナルよりだいぶ処理がスッキリしました。

親クラス定義・$superの初期値書き換え問題の解決

親クラス定義・$superの初期値の書き換えの問題も解決してます。

var Aaa = MyClass.create({
    init : function(a){
        this.a = a||this.a;
        return this;
    },
    putA : function(){
        alert('a is '+ this.a);
    },
    a : 'A'
});
var Bbb = MyClass.create(Aaa,{
    init : function(b){
        this.$super.init(b)
        return this;
    }
});

Aaa(123).putA();    //a is 123 (OK)
Aaa().putA();       //a is A (OK)
Bbb(456).putA();    //a is 456 (OK)
Aaa().putA();       //a is A (OK)
Bbb().putA();       //a is A (OK)
ネストしたオブジェクト定義の別インスタンス管理

ネストしたオブジェクト定義(以下のstsA,stsB)も新しく生成される別のインスタンスで管理されます。

var Aaa = MyClass.create({
    init : function(a){
        this.a = a || this.a
        return this;
    },
    showA : function(){
        this.stsA.showCnt ++;
        alert('a is '+this.a + ' / showCnt:'+this.stsA.showCnt);
        return this;
    },
    stsA : {
        showCnt : 0
    },
    a : 'A' 
})
var Bbb = MyClass.create(Aaa,{
    init : function(a,b){
        this.$super.init(a)
        this.b = b || this.b;
        return this;
    },
    showB : function(){
        this.stsB.showCnt ++;
        alert('b is '+this.b + ' / showCnt:'+this.stsB.showCnt);
        return this;
    },
    stsB : {
        showCnt : 0
    },
    b : 'B' 
})
Bbb('AAA','BBB')
    .showA()	//	a is AAA / showCnt:1
    .showB()	//	b is BBB / showCnt:1
;
Aaa()
    .showA()	//	a is A / showCnt:1
;
Bbb()
    .showA()	//	a is A / showCnt:1
    .showB()	//	b is B / showCnt:1
    .showA()	//	a is A / showCnt:2
    .showB()	//	b is B / showCnt:2
;
Bbb('','bbb')
    .showA()	//	a is A / showCnt:1
    .showB()	//	b is bbb / showCnt:1
;

シンプル版 myclass.js

ちなみにネストしたオブジェクト定義の別インスタンス生成が不要な場合は、以下のようもう少しソースがシンプルになります。

(function(){
    window.MyClass = {
        create : function(c,e){
            var f = function(){
                var ins;
                return (ins=MyClass.getMyInstance(f)).init.apply(ins,arguments);
            }
            f.__member__ = e||c;
            if(e)e.__c__=c;
            return f;
        },
        getMyInstance : function(f){
            var util = MyClass.MyUtil;
            if (f.__member__.__c__) {
                var ins = MyClass.getMyInstance(f.__member__.__c__)
                var $super = ins;
                ins = util.extend(
                        util.getInstance($super),util.getInstance(f.__member__)
                );
                ins.$super = $super;
                ins.MyUtil=util;
                return ins;
            }
            return util.getInstance(f.__member__||f);
        }
    }
    window.MyClass.MyUtil = {
        extend : function(obj,ext){
            for(var i in ext)obj[i]=ext[i];
            return obj;
        },
        getInstance : function(obj){
            var f;
            (f = function(){}).prototype = obj;      
            return new f;
        }
    }
})();