読者です 読者をやめる 読者になる 読者になる

オブジェクト指向な大規模JS開発とかに便利なクラス定義JS(ネームスペースとpublic,private分離)作ってみたよ

(2009/3/6)バグを調整

オブジェクト指向な大規模JS開発とかに便利なクラス定義JS(ネームスペースとpublic,private分離)作ってみたよ
複数人が書くと、結構みんなばらばらの書き方になっちゃうし。


特徴は

  • ネームスペース定義できる
  • privateとpublicの分離
  • 固定されたクラス定義シンタックス

等です


使い方

  • public,private,protected staticの順に定義します
  • public内、private内であればthis参照でいけます
  • またpublic,privateをまたいでコールする場合には、this.public、this.privateのスコープでコールする必要があります
  • staticなど必要ないところは未指定で飛ばすことができます
  • コンストラクタはパブリック空間にConstructを定義すればOK(引数の制限などはありません)
Class.register( "com.somedomain.SomeClass" , {
 		//PUBLIC MEMBERS
 	},{
 		//PRIVATE MEMBERS
 	},{
 		//STATIC MEMBERS
 	}
});

テスト

■テストクラス

    Class.register( "net.toytools.TestClass" , {
        //PUBLIC MEMBERS
        publicMember:null,
        Construct:function( value ){
            this.publicMember = value;
            console.log("Construct : " + value);
        },
        publicMethod:function(){
            //public to private
            this.private._publicToPrivate();
            
            //public to public
            this.publicToPublic( "THIS SCOPE" );
            this.public.publicToPublic( "PUBLIC SCOPE" );
        },
        privateToPublic:function(){
            console.log( "privateToPublic : " + this.publicMember );
        },
        publicToPublic:function( value ){
            console.log( "publicToPublic : " + value );
        }
    } , {
        //PRIVATE MEMBERS
        _publicToPrivate:function(){
            console.log("_publicToPrivate : "  + this.public.publicMember);
            //private to public
            this.public.privateToPublic();
        }
    } ,{
        //STATIC MEMBERS
        TEST_STATIC_VAR:"test static var!!",
        testStaticMethod:function(){
            console.log("testStaticMethod");
        }
    } );


■実行

    net.toytools.TestClass.testStaticMethod();
    var o1 = new net.toytools.TestClass( "Construct Arguments" );
    o1.publicMethod();

■結果

testStaticMethod
Construct : Construct Arguments
_publicToPrivate : Construct Arguments
privateToPublic : Construct Arguments
publicToPublic : THIS SCOPE
publicToPublic : PUBLIC SCOPE

ソース

ソース

そのうちどっかにあげるかもだけどめんどくさいのでとりあえず。

/**
 * (c) kaw( http://d.hatena.ne.jp/toytools/ )
 */
var Class = function( ){
    var pub = {
        /**
         * クラスを登録する.
         * @param   namespace       クラスまで含んだネームスペース文字列(例:"net.toytools.TestClass")
         * @param   publicMembers   パブリックメンバーオブジェクト
         * @param   privateMembers  プライベートメンバーオブジェクト
         */
        register:function( namespace , publicMembers , privateMembers , staticMembers ){
            if( !publicMembers ) publicMembers = {};
            if( !privateMembers ) privateMembers = {};
            if( !staticMembers ) staticMembers = {};
            var pub = function(){}
            var pri = function(){}
            pub.prototype = publicMembers;
            pri.prototype = privateMembers;
            var splittedNamespace = namespace.split('.');
            var clazz = function(){
                var pubIns  = new pub();
                var priIns  = new pri();
                pubIns.private = priIns;
                priIns.public  = pubIns;
                pubIns.public  = pubIns;
                priIns.private = priIns;
                if( pubIns["Construct"] ) pubIns.Construct.apply( pubIns , arguments )
                return pubIns;
            };
            staticMembers.__CLASS_NAME__ = namespace;
            for( var i in staticMembers ){
                clazz[i] = staticMembers[i];
            }
            _registerClass( splittedNamespace , clazz , _namespacesRoot );
            _namespacesDic[namespace] = clazz;
        },
        /**
         * クラスを取得する.
         * @param   namespace       ネームスペース文字列
         */
        get:function( namespace ){
            return _namespacesDic[namespace];
        },
        /**
         * クラスは登録されているか.
         * @param   namespace       ネームスペース文字列
         */
        isRegistered:function( namespace ){
            return _namespacesDic[namespace] != undefined;
        }
    };
    //PRIVATE MEMBERS
    var _namespacesRoot = window;
    var _namespacesDic  = {};
    var _registerClass  = function( splittedNamespace , registerClass , nextTarget ){
        var next = splittedNamespace.shift();
        if( nextTarget[next] == undefined ) nextTarget[next] = {};
        if( splittedNamespace.length == 0 ){
            nextTarget[next] = registerClass;
            return nextTarget[next];
        }else{
            return _registerClass( splittedNamespace , registerClass , nextTarget[next] );
        }
    }
    return pub;
    
}();