オブジェクト指向な大規模JS開発とかに便利なクラス定義JS(ネームスペースとpublic,private分離)作ってみたよ
(2009/3/6)バグを調整
オブジェクト指向な大規模JS開発とかに便利なクラス定義JS(ネームスペースとpublic,private分離)作ってみたよ
複数人が書くと、結構みんなばらばらの書き方になっちゃうし。
特徴は
- ネームスペース定義できる
- privateとpublicの分離
- 固定されたクラス定義シンタックス
等です
使い方
- public,private,
protectedstaticの順に定義します - 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; }();