博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS模拟类继承
阅读量:6111 次
发布时间:2019-06-21

本文共 2514 字,大约阅读时间需要 8 分钟。

hot3.png

    //最后一个参数是JSON表示的类定义

    //如果参数大于一,则第一个参数是基类,否则,基类是object

    //中间的参数是类实现的接口

    //返回值是类,类是一个构造函数,并继承了基类的prototype

 

    

function Class(){

        aDefine = arguments[arguments.length - 1]; //传入的最后一个参数是要定义的类

        if(!aDefine) return; //如果没用传参数,则直接结束。

        var aBase = arguments.length>1?arguments[0]:object; //如果传的参数大于1,则第一个参数为基类,若等于1,则基类默认为object

        function prototype_(){}; //创建prototype临时函数,用以挂接原型链

        prototype_.prototype = aBase.prototype;

        var aPrototype = new prototype_(); //建立类要使用的原型对象

        for(var member in aDefine){

            if(aDefine[member] != 'Create'){ //构造函数不用挂在原型链上,构造函数是最终返回的

                aPrototype[member] = aDefine[member];

            }

        }

        //设置类

        if(aDefine.Create){  //如果有构造函数

            var aType = aDefine.Create; //类即为该构造函数

        }else{ //如果没有构造函数

            var aType = function(){ //创建默认的构造函数

                this.base.apply(this, arguments); //调用父类的构造函数

            }

        }

        aType.prototype = aPrototype;  //设置类(构造函数)的原型

        aType.Base = aBase; //设置类型关系

        aType.prototype.Type = aType; //为本类对象扩展一个Type属性,用以判断对象的类型

        return aType; //将加了原型继承的构造函数返回,就可以new了

    }

    function object(){}; //定义object根类,用以实现最基础的方法和属性

    object.prototype.isA = function(type){ //判断对象属性是否属于某种类型

        var self = this.Type;

        while(self){

            if(self == type){

                return true;

            }

            self = self.Base;

        }

        return false;

    }

    object.prototype.base = function(){   //调用基类的构造函数

        var Caller = object.prototype.base.caller; //得到调用该函数的函数

        Caller && Caller.Base && Caller.Base.apply(this, arguments);

        //如果Caller存在并且 Caller.Base存在,则调用 Caller.Base方法

        //若果如果Caller或Caller.Base有一个不存在,那么后面的语句不用再执行。

    }

    var people = Class({ //定义people类

        Create: function(name, age){

            this.base();

            this.name = name;

            this.age = age;

        },

        say: function(){

            console.log('My name is ' + this.name + ",I'm " + this.age + '.');

        }

    })

    var chinaPeople = Class(people,

        {

            Create: function(name, age, country){

                this.base(name, age);

                this.country = country;

            },

            sayCountry: function(){

                console.log('My country is ' + this.country);

            }

        }

    )

    var man1 = new people('kaka', 32);

    var man2 = new chinaPeople('kaka', 32, 'china');

    man2.say();  //My name is kaka,I'm 32.

    man2.sayCountry();  //My country is china 

caller不支持opera浏览器,所以重写base方法

  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(!Type.Base) return Base //基类已无基类,就无需包装

            return function(){ //包装为引用临时变量Base的闭包函数

                this.base = MakeBase(Base); //先复写this.base

                Base.apply(this, arguments); //在调用基类构造函数

            }

        }

    }

转载于:https://my.oschina.net/u/1992917/blog/358025

你可能感兴趣的文章
第 9 章 MySQL数据库Schema设计的性能优化
查看>>
前nginx后Apache+Node反向代理
查看>>
Web前端开发十日谈
查看>>
关于jsp页面乱码写得好的一篇文章
查看>>
Linux 基础知识
查看>>
写了一个采集的类,个人感觉不错,代码普通,但灵活性高
查看>>
collector v1.02采集核心代码版本升级中
查看>>
ddns动态域名解析系统
查看>>
Spring Data Redis 2 之消息订阅
查看>>
centos中如何查看tomcat的版本
查看>>
[XML/RSS] XML加ASP实现网页自动适应多国语言
查看>>
Android小笔记自定义控件
查看>>
学会思考
查看>>
docker 镜像仓库Harbor https访问
查看>>
dblink创建
查看>>
磁盘管理
查看>>
luov之SMTP报错详解
查看>>
软件概要设计做什么,怎么做
查看>>
dwr
查看>>
java的特殊符号
查看>>