博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js原型链继承
阅读量:7081 次
发布时间:2019-06-28

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

js原型链继承有很多种实现的方式,主要介绍以下3种:

一、拷贝继承:

顾名思义拷贝就是利用for in 或者jq的extend,把一个构造函数的prototype循环遍历赋值给另一个构造函数的prototype,再把构造函数内的属性也一起继承过去

var Base = function(name){        this.name = name;    };    Base.prototype.getName = function(){        alert(this.name);    };    var Aaa = function(name,sex){        //继承属性        Base.call(this,name);        this.sex = sex;    };    //继承方法    extend(Aaa.prototype,Base.prototype);    //调用:    var a = new Aaa('小明','男');    a.getName();

 

二、类式继承:

  1. 构造函数A.prototype = new 构造函数B();
  2. 继承属性
  3. 修改构造函数指向
var Base = function(){        this.cacheName = [];    };    Base.prototype.addName = function(name){        this.cacheName.push(name);    };    Base.prototype.getNames = function(){        alert(this.cacheName);    };    var Aaa = function(){        //继承属性        Base.call(this);    };    //继承方法    Aaa.prototype = new Base();    //修改构造函数指向    Aaa.prototype.constructor = Aaa;    //调用:    var a = new Aaa();    a.addName('小明');    a.getNames();

 

三、原型继承:

利用es5新特性Object.create实现原型继承

Object.create = Object.create || function(o){        var F = function(){};        F.prototype = o;        return new F();    };

Object.create的作用是只继承方法不继承属性

与类式继承一样需要继承属性、修改构造函数指向

var Base = function(name){        this.name = name;    };    Base.prototype.getName = function(){        alert(this.name);    };    var Aaa = function(){        //继承属性        Base.apply(this,arguments);    };    //继承方法    Aaa.prototype = Object.create(Base.prototype);    //修改构造函数指向    Aaa.prototype.constructor = Aaa;    var a = new Aaa('小明');    a.getName();        Object.create = Object.create || function(o){        var F = function(){};        F.prototype = o;        return new F();    };

 

通用的原型链继承:

Object.create = Object.create || function(o){        var F = function(){};        F.prototype = o;        return new F();    };    function Class(){};    Class.extend = function(opts){        //父类的原型链        var _super = this.prototype;        var prototype = Object.create(_super);        for(var prop in opts){            var val = opts[prop];            prototype[prop] = val;        }        var Fn = function(){            this.init && this.init.apply(this,arguments);        };        //继承方法        Fn.prototype = prototype;        //修改构造函数指向        Fn.prototype.constructor = Fn;        //把父类的所有方法保存到超类        Fn.prototype._super = Object.create(_super);        //递归调用Class.extend方法        Fn.extend = arguments.callee;        return Fn;    };

 

调用:

var Person = Class.extend({        init:function(opts){            opts = opts || {};            this.name = opts.name;            this.sex = opts.sex;            this.age = opts.age;        },        getName:function(){            return this.name;        },        getSex:function(){            return this.sex;        },        getAge:function(){            return this.age;        }    });    var Student = Person.extend({        init:function(opts){            opts = opts || {};            this.job = opts.job;            this._super.init.call(this,opts);        },        getJob:function(){            return this.job;        },        getInfo:function(){            alert('name:' + this.getName() + ',sex:' + this.getSex() + ',age:' + this.getAge() + ',job:' + this.getJob());        }    });    var student = new Student({        name:'小明',        sex:'男',        age:18,        job:'学生'    });    student.getInfo();

 

我们发现子类调用父类的方法有些不方便:this._super.init.call(this,opts);

var Student = Person.extend({        init:function(opts){            opts = opts || {};            this.job = opts.job;            this._super.init.call(this,opts);        },        .......................    });

而且这种添加超类的方式性能也很差。如果子类没有调用超类,那么创建超类就是一种浪费。

Fn.prototype._super = Object.create(_super);

 

利用闭包改写Class.extend方法:

Object.create = Object.create || function(o){        var F = function(){};        F.prototype = o;        return new F();    };    var fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;    function Class(){};    Class.extend = function(opts){        //父类的原型链        var _super = this.prototype;        var prototype = Object.create(_super);        for (var prop in opts) {                        var val = opts[prop];            prototype[prop] = typeof val == "function" &&            typeof _super[prop] == "function" && fnTest.test(val) ?                (function(prop, fn){                    return function() {                        var tmp = this._super;                        //在调用fn方法前创建一个超类                        this._super = _super[prop];                        //该方法只需要暂时绑定,所以在执行完毕后将其移除                        var ret = fn.apply(this, arguments);                        this._super = tmp;                                                return ret;                    };                })(prop, val) :                val;        }        var Fn = function(){            this.init && this.init.apply(this,arguments);        };        //继承父级的所有方法        Fn.prototype = prototype;        //修改构造函数指向        Fn.prototype.constructor = Fn;        //递归调用Class.extend方法        Fn.extend = arguments.callee;        return Fn;    };

 

调用:

var Student = Person.extend({        init:function(opts){            opts = opts || {};            this.job = opts.job;            this._super(opts);        },                ...................    });

 

现在调用也很方便了,无需修正this的指向。

当调用原型方法前创建超类,调用后即销毁它。而且超类只保存了对应父类的一个方法,并不是保存父类所有的方法。

(function(prop, fn){                    return function() {                        var tmp = this._super;                        //在调用fn方法前创建一个超类                        this._super = _super[prop];                        //该方法只需要暂时绑定,所以在执行完毕后将其移除                        var ret = fn.apply(this, arguments);                        this._super = tmp;                                                return ret;                    };                })(prop, val)

 

转载于:https://www.cnblogs.com/gongshunkai/p/6650215.html

你可能感兴趣的文章
Spring Cloud Zuul过滤器详解
查看>>
使用DOM4J创建一个新的XML文件
查看>>
VIM使用系列:搜索功能
查看>>
SOAP--------Golang对接WebService服务实战
查看>>
7大维度看国外企业为啥选择gRPC打造高性能微服务?
查看>>
初创公司电商系统建立思考
查看>>
微服务框架Spring Cloud介绍 Part2: Spring Cloud与微服务
查看>>
linux系统下设置时间同步
查看>>
dubbo源码学习笔记----整体结构
查看>>
zipfile
查看>>
基于Dockerfile编译镜像并上传到Docker Hub公共仓库教程
查看>>
很形象地展示了进程与线程的区别
查看>>
代码即财富之我学Java比较器(7)
查看>>
记一次dubbo连接超时分析
查看>>
【译】Envoy threading model
查看>>
mysql主从复制
查看>>
karaf相关知识点
查看>>
鸥几里得算法,求两人个整数的最大公因数
查看>>
Selective Packet Discard
查看>>
20年的老程序员对新入行的朋友的一些建议
查看>>