首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > JavaScript >

发个JS练手创作,简单的OO封装

2013-03-14 
发个JS练手作品,简单的OO封装最近翻书复习了下基础知识,感觉书上的面向对象的例子用起来不是很顺手所以自

发个JS练手作品,简单的OO封装
最近翻书复习了下基础知识,感觉书上的面向对象的例子用起来不是很顺手
所以自己改了下,纯粹练手,有意见的请拍砖,当然最好能给出更好的例子。

var $class = (function(){       
        var guid = 0,
        classMap  = {},
        caller    = null,
        callStack = [];
       
        return {
                create : createClass
        }
       
        //------------------------[辅助函数部分]------------------------
   
    /**
    * 创建新类.
    * @param  {constructor}superClass   超类构造器,该类必须由$class.create创建
    * @param  {Json}proto               类原型
    * @return {constructor}
    */
        function createClass(superClass, proto){
        var isSuperValid =  superClass instanceof Function
                         && superClass.prototype
                         && superClass.prototype.init instanceof Function;            
        
        superClass = isSuperValid ? superClass : null;
                  
                var superProto = superClass ? superClass.prototype : null;
                        
                //定义类构造函数
                var klass = function() {
                        var args = [].slice.call(arguments);
                       
                        //执行父类构造函数.
                        if(superClass){                                       
                                superClass.apply(this, args);


                        }
               
                        //若自己的原型中有init方法,执行init
                        if(klass.prototype.hasOwnProperty('init')){
                                klass.prototype.init.apply(this, args);
                        }       
                };
               
                //定义类原型
                var klassProto = getClassProto(superProto, proto);               
                klassProto.constructor = klass;
                klass.prototype = klassProto;
               
                //返回类
                return klass;
        }
       
    /**
    * 获取类原型.
    * @param  {json}superProto  超类原型
    * @param  {Json}overwrites  需要重写方法
    * @return {json}
    */
        function getClassProto(superProto, overwrites) {
                var i, F, proto, classId = getGuid();
               
                if(superProto){
                        F = function(){};
                        F.prototype = superProto;
                        proto = new F();
                }else{
                        proto = getDefaultProto();
                }


               
                //用overwrites中方法覆盖原型中的方法
                for(i in overwrites){
                        if(overwrites.hasOwnProperty(i)){
                                proto[i] = overwrites[i];
                        }       
                }
        
        //修复IE中for in不能遍历toString、valueOf等属性的Bug
        if(document.all){
            var len, method, methods = ['toString', 'valueOf'];
            for(i=0, len = methods.length; i < len; i++){
                method = methods[i];
                if( overwrites.hasOwnProperty(method) ){
                    proto[method] = overwrites[method];
                }
            }
        }        
               
                //注册类关系       
                proto.classId = classId;
                regClass(proto, superProto);
               
                //确保原型中含有必要的原型方法
                addMastHasMethods(proto);
               
                return proto;       
        }
       
    /**
    * 获取默认原型.
    * @return {json}
    */
        function getDefaultProto(){
                return {
                        init : function(){},                       


                        callSuper : callSuper
                };
        }
       
    /**
    * 调用超类方法.
    * @param  {String}methodName   方法名
    * @return
    */
        function callSuper(methodName){
                caller        = (caller === null ? this : caller);
               
                var curClsId = callStack.length > 0
                     ? callStack[callStack.length - 1]
                     : this.classId;
        
        var args   = [].slice.call(arguments, 1),
            parent = getParent(curClsId),
            ret;
            
                if(parent && parent[methodName]){
            callStack.push(parent.classId);
                       
            try{
                ret = parent[methodName].apply(caller, args);
            }catch(e){
                alert(e);
                        }
                       
                        callStack.pop();
                }

                //调用完毕后将调用上下文清空
                if(callStack.length === 0){
                        caller = null;
                }
        
        return ret;


        }
       
    /**
    * 将类信息注册到类记录表中.
    * @param {json}proto    类原型.
    * @param {json}parent   超类原型
    */
        function regClass(proto, superProto){
                var classId  = proto.classId;
               
                classMap[classId] = {
                        id    : classId,
                        proto : proto,
                        parent: superProto
                };               
        }               
       
    /**
    * 检查原型链中是否有必须要实现的方法,没有的话,向原型中添加.
    * @param {json}proto
    */
        function addMastHasMethods(proto){
                var i, dftProto = getDefaultProto();
                for(i in dftProto){
                        if(dftProto.hasOwnProperty(i) && !proto[i]){
                                proto[i] = dftProto[i];
                        }
                }
        }       
       
    /**
    * 获取guid.
    * @return {int}
    */
        function getGuid(){
                return guid++;
        }
       
    /**
    * 获取超类原型.
    * @param  {int}classId   类ID
    * @return {json}         超类原型, 若存在返回null.
    */
        function getParent(classId){


                var record = classMap[classId];
                return record ? record.parent : null;       
        }
})();

var Man = $class.create(null, {
    init : function(cfg){
        this.name = cfg.name;
        this.age  = cfg.age;  
    },
   
    say : function(){
        alert('my name is:' + this.name + ", " + this.age);
    },
   
    toString : function(){
        return (
             'name: ' + this.name
           + ', age: ' + this.age
        );
    }
});

var Student = $class.create(Man, {
    init : function(cfg){           //执行此方法前会自动调用Man.init
        this.stuNum = cfg.stuNum;
    },
   
    say : function(){
        this.callSuper('say');      //调用父类方法
        alert("i'm a student, my student number is " + this.stuNum);
    },
   
    toString : function(){
        return (
              this.callSuper('toString')
            + ', stuNum: ' + this.stuNum
        );        
    }
});

window.onload = function(){
    var m1 = new Man({name : '张三', age: 20}),
        s1 = new Student({
            name    : '王五',
            age     : 22,
            stuNum  : 'no-1'
        });
   
    m1.say();
    s1.say();   
    alert(m1.toString() + "\n" + s1.toString());
};


------解决方案--------------------


楼主好人,copy学习下
[解决办法]
发个JS练手创作,简单的OO封装
[解决办法]
$class.create(null, {
    init : function(cfg){
        this.name = cfg.name;
        this.age  = cfg.age;  
    }

建议把这个null省略掉
[解决办法]
一直不怎么喜欢以OO方式写JS,不过大势所趋,代码多了也确实OO会方便些

收藏以备深入学习发个JS练手创作,简单的OO封装
[解决办法]
喜欢OO也喜欢XX
[解决办法]
楼主算法的目的是什么?
[解决办法]
算法核心部分应该就是继承的功能,LZ应该是出于这个目的

尽可能的向OO靠齐
[解决办法]
支持,这么写一边自己对OO又加深了印象
[解决办法]
楼看过mootool源码吧。
[解决办法]
要需要在重写的方法中引用
父类的方法。
[解决办法]
姑且不说别的 代码写的很规整 境界很高深 我无比敬佩 这才是一个优秀的coding开发人员 我顶你~~~
[解决办法]
楼主强大,咱JS还在入门中,表示看不懂这些
[解决办法]
这。。。。好深奥啊,新手表示看不懂
[解决办法]
楼主应该写点注释
[解决办法]
谢谢分享。。。。。。。。。。。。。
[解决办法]


[解决办法]
太高深了
[解决办法]
哎。看不懂呐。




--------------------------------------帅签分割线-------------------------------------------------
发个JS练手创作,简单的OO封装
[解决办法]
学习了。
[解决办法]
这么写主要是为了解决JS继承中一个很麻烦的问题:
你既要重写父类的方法,要需要在重写的方法中引用
父类的方法。
===========================
function merge(a, b)  //ensure a and b are both 'function' type
{
if(a && a != b)
{
  var merged = function(){
    this.__super__ = arguments.callee.__super__;
    return b.apply(this, arguments);
  }
  merged.__super__ = a;
  return merged;
}
return a;
}
在getClassProto中的循环检查同名函数然后merge。
在实例中可以直接在各个方法内直接this.__super__(1,2,3);


省去callStack另外init也能__super__
如say : function(str)
{
this.__super__();
alert('say:' + str);
}

[解决办法]
mark
[解决办法]
学习一下
[解决办法]
楼主看的什么书啊?
[解决办法]
楼主写点注释啊,要不新手看不懂。
[解决办法]
厉害。oo确实使用很方便。
oo 再加上VS2010,那真是完美了






-----------------------------

新版老虎插件即将登场:发个JS练手创作,简单的OO封装
[解决办法]
牛人呀·····
[解决办法]
发个JS练手创作,简单的OO封装
[解决办法]
不知道js面向对象是不是真的大势所趋
[解决办法]
看不懂啊看不懂。。。
[解决办法]



(function(){
var Base = window.Base = Base 
[解决办法]
 {
        ///summary: 静态方法,创建抽象类
        create: function () {
            return function () {
                this.initialize.apply(this, arguments);
            }
        },
        ///summary: 静态方法,实现继承,允许重载
        extend: function () {
            if (1 == arguments.length) {
                for (var p in arguments[0]) this[p] = arguments[0][p];
                return this;
            };
            for (var p in arguments[1]) arguments[0][p] = arguments[1][p];
            return arguments[0];
        },
        ///summary: Cookie类
        Cookie: function () {
            var Cookie = Base.create();
            Cookie.prototype = {
                initialize: function () { },
                ///写cookie
                setCookie: function (name, value) {


                    var date = new Date();
                    date.setTime(date.getTime() + 30 * 24 * 3066 * 1000);
                    document.cookie = name + "=" + value + ";expires=" + date.toGMTString()
                },
                ///读cookie
                getCookie: function (name) {
                    var CookieArray = document.cookie.split(";");
                    for (var i = 0; i < CookieArray.length; i++) {
                        var arr = CookieArray[i].split("=");
                        if (arr[0] == name) {
                            return arr[1];
                            break;
                        }
                    }
                },
                ///清除cookie
                clearCookie: function (name) {
                    document.cookie = name + "=''; expires=Thu, 01-Jan-70 00:00:01 GMT";
                }
            }
            return new Cookie();
        }
    };
})();


[解决办法]
楼主强大
[解决办法]
该回复于2012-05-19 10:12:41被版主删除
[解决办法]
留下脚印,copy
[解决办法]
向老鸟看齐,顶楼主
[解决办法]


mark &  up

留备以后学习
[解决办法]
看不太懂,但是还是认真看完了,
[解决办法]
厉害啊!不错的

热点排行