网络编程
位置:首页>> 网络编程>> JavaScript>> 《悟透JavaScript》之 甘露模型(4)

《悟透JavaScript》之 甘露模型(4)

作者:李战 来源:软件真谛 发布时间:2008-06-09 14:03:00 

标签:类,class,javascript,模型

这可真是闭包中嵌套着闭包,貌似递归却又不是递归,是高阶函数却又高不可测。一旦整个对象创建完成,用过的内存状态都释放得干干净净,只得到一尘不染的新建对象。JavaScript玩到这样的境界,方显观音大士的法力!

    下面就是是重写后的完美甘露模型代码:

http://www.leadzen.cn/Books/WuTouJavaScript/1/JS25.htm


<script type="text/javascript">
    //定义类的语法甘露:Class()
    //最后一个参数是JSON表示的类定义
    //如果参数数量大于1个,则第一个参数是基类
    //第一个和最后一个之间参数,将来可表示类实现的接口
    //返回值是类,类是一个构造函数
    function Class()
    {
        var aDefine = arguments[arguments.length-1]; //最后一个参数是类定义
        if(!aDefine) return;
        var aBase = arguments.length>1 ? arguments[0] : object; //解析基类
        
        function prototype_(){}; //构造prototype的临时函数,用于挂接原型链
        prototype_.prototype = aBase.prototype;  //准备传递prototype
        var aPrototype = new prototype_();    //建立类要用的prototype
        
        for(var member in aDefine)  //复制类定义到当前类的prototype
            if(member!="Create")    //构造函数不用复制
                aPrototype[member] = aDefine[member];
                
        //根据是否继承特殊属性和性能情况,可分别注释掉下列的语句
        if(aDefine.toString != Object.prototype.toString)
            aPrototype.toString = aDefine.toString;
        if(aDefine.toLocaleString != Object.prototype.toLocaleString)
            aPrototype.toLocaleString = aDefine.toLocaleString;
        if(aDefine.valueOf != Object.prototype.valueOf)
            aPrototype.valueOf = aDefine.valueOf;
if(aDefine.Create)  //若有构造函数
            var aType = aDefine.Create  //类型即为该构造函数
        else    //否则为默认构造函数
            aType = function()
            {
                this.base.apply(this, arguments);   //调用基类构造函数
            };
aType.prototype = aPrototype;   //设置类(构造函数)的prototype
        aType.Base = aBase;             //设置类型关系,便于追溯继承关系
        aType.prototype.Type = aType;   //为本类对象扩展一个Type属性
        return aType;   //返回构造函数作为类
    };
//根类object定义:
    function object(){}    //定义小写的object根类,用于实现最基础的方法等
    object.prototype.isA = function(aType)   //判断对象是否属于某类型
    {
        var self = this.Type;
        while(self)
        {
            if(self == aType) return true;
            self = self.Base;
        };
        return false;
    };
    
    object.prototype.base = function()  //调用基类构造函数
    {
        var Base = this.Type.Base;  //获取当前对象的基类  
        if(!Base.Base)  //若基类已没有基类
            Base.apply(this, arguments)     //则直接调用基类构造函数
        else    //若基类还有基类         
        {
            this.base = MakeBase(Base);     //先覆写this.base
            Base.apply(this, arguments);    //再调用基类构造函数
            delete this.base;               //删除覆写的base属性
        };
        function MakeBase(Type) //包装基类构造函数
        {
            var Base = Type.Base;
            if(!Base.Base) return Base; //基类已无基类,就无需包装
            return function()   //包装为引用临时变量Base的闭包函数
            {
                this.base = MakeBase(Base);     //先覆写this.base
                Base.apply(this, arguments);    //再调用基类构造函数
            };
        };
    };
//语法甘露的应用效果:    
    var Person = Class      //默认派生自object基本类
    ({
        Create: function(name, age)
        {
            this.base();    //调用上层构造函数
            this.name = name;
            this.age = age;
        },
        SayHello: function()
        {
            alert("Hello, I'm " + this.name + ", " + this.age + " years old.");
        },
        toString: function()    //覆写toString方法
        {
            return this.name;
        }
    });
    
    var Employee = Class(Person,    //派生自Person类
    {
        Create: function(name, age, salary)
        {
            this.base(name, age);  //调用基类的构造函数
            this.salary = salary;
        },
        ShowMeTheMoney: function()
        {
            alert(this + " $" + this.salary); //这里直接引用this将隐式调用toString()
        }
    });
var BillGates = new Person("Bill Gates", 53);
    var SteveJobs = new Employee("Steve Jobs", 53, 1234);
    alert(BillGates);   //这里将隐式调用覆写后的toString()方法
    BillGates.SayHello();
    SteveJobs.SayHello();
    SteveJobs.ShowMeTheMoney();
    
    var LittleBill = new BillGates.Type("Little Bill", 6); //用BillGate的类型建LittleBill
    LittleBill.SayHello();
    
    alert(BillGates.isA(Person));       //true
    alert(BillGates.isA(Employee));     //false
    alert(SteveJobs.isA(Person));       //true
</script>

当今的JavaScript世界里,各式各样的AJAX类库不断出现。同时,在开放Web API的大潮中,AJAX类库作为Web API最重要的形式,起着举足轻重的作用。这些AJAX类库是否方便引用,是否易于扩展,是否书写优雅,都成了衡量Web API质量的重要指标。

甘露模型基于JavaScript原型机制,用及其简单的Class()函数,构造了一个非常优雅的面向对象的类机制。事实上,我们完全可以在这个甘露模型的基础上打造相关的的AJAX类库,为开发人员提供简洁而优雅的Web API接口。

想必微软那些设计AJAX架构的工程师看到这个甘露模型时,肯定后悔没有早点把AJAX部门从美国搬到咱中国的观音庙来,错过了观音菩萨的点化。

当然,我们也只能是在代码的示例中,把Bill Gates当作对象玩玩,真要让他放弃上帝转而皈依我佛肯定是不容易的,机缘未到啊!如果哪天你在微软新出的AJAX类库中看到这种甘露模型,那才是真正的缘分!

广告时间:《悟透JavaScript》一书,共分三部分,
       第一部分 JavaScript真经 (博客原文扩编)
       第二部分 手谈JavaScript (讲述JavaScript操纵DOM)
       第三部分 点化AJAX (AJAX思维升华)

就算你不看,也可以给孩子当故事书。如果你还没孩子,就当给自己买本幽默的漫画书。

原创 * :李战(leadzen)

幕后指使:电子工业出版社-博文视点公司

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com