微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Js继承的实现方式

Js继承的实现方式

继承是面向对象软件技术当中的一个概念,与多态、封装共为面向对象的三个基本特征。继承可以使得子类具有父类属性方法或者重新定义、追加属性方法等。

原型链继承

通过将子类的原型对象指向父类的实例,实现继承访问父类属性方法

// 定义父类
function Parent(){
    this.name = "parent";
    this.say = function(){
        console.log(this.name);
    }
}
// 定义子类
function Child(){
    this.name = "child";
}
Child.prototype = new Parent(); // 将子类的原型对象指向父类的实例
Child.prototype.construce = Child; // 修复constructor使符合原型链规定
var child = new Child(); // 实例化子类
child.say(); // child // 此时子类能够访问父类的say方法,在查找name属性的时候首先在自身属性中查找成功所以不再向上查找,若子类没有name成员,则会打印parent
console.log(child instanceof Parent); // true // 判断child的构造函数Child的prototype对象是否在Parent的原型链上

特点

不足

构造函数继承

当子类构造函数调用时,借助call或者apply调用父类构造方法实现对于this的拓展

// 定义父类
function Parent(from){
    this.name = "parent";
    this.say = function(){
        console.log(this.name);
    }
    this.from = from;
}
// 定义子类
function Child(from){
    Parent.call(this,from); // 调用父类构造函数并绑定this来拓展Child实例成员方法,可以传递参数
    this.name = "child";
}

var child = new Child("child"); // 实例化子类
child.say(); // child
console.log(child.from); // child

特点

不足

实例继承

为父类实例增加成员与方法,作为实例返回

// 定义父类
function Parent(from){
    this.name = "parent";
    this.say = function(){
        console.log(this.name);
    }
    this.from = from;
}
// 定义子类
function Child(from){
    var instance = new Parent(from);
    instance.name = "child";
    return instance;
}

var child = new Child("child"); // 实例化子类
child.say(); // child
console.log(child.from); // child

特点

  • 实例化子类时可以向父类构造函数传参
  • 子类的实例化方式可以为new Child()或直接调用Child()

不足

拷贝继承

通过直接将父类属性拷贝到子类的原型中实现继承

// 定义父类
function Parent(from){
    this.name = "parent";
    this.say = function(){
        console.log(this.name);
    }
    this.from = from;
}
// 定义子类
function Child(from){
    var instance = new Parent(from);
    for(let item in instance) Child.prototype[item] = instance[item];
    this.name = "child";
}

var child = new Child("child"); // 实例化子类
child.say(); // child
console.log(child.from); // child

特点

不足

原型式继承

通过共享原型对象实现继承

// 定义父类
function Parent(){}
Parent.prototype.name = "parent";
Parent.prototype.say = function(){ console.log(this.name); }

// 定义子类
function Child(from){
    this.name = "child";
}

Child.prototype = Parent.prototype; // 共享原型
Child.prototype.construce = Child;

var child = new Child("child"); // 实例化子类
child.say(); // child

特点

不足

组合继承

组合原型链继承和借用构造函数继承,结合了两种模式的优点,传参和复用

// 定义父类
function Parent(from){
    this.name = "parent";
    this.say = function(){
        console.log(this.name);
    }
    this.from = from;
}
// 定义子类
function Child(from){
    Parent.call(this,from);
    this.name = "child";
}

Child.prototype = new Parent();
Child.prototype.construce = Child;

var child = new Child("child"); // 实例化子类
child.say(); // child
console.log(child.from); // child

特点

不足

寄生组合继承

通过寄生方式,砍掉父类的实例属性,在调用两次父类的构造的时候,就不会初始化两次实例方法属性,避免的组合继承的缺点

// 定义父类
function Parent(from){
    this.name = "parent";
    this.say = function(){
        console.log(this.name);
    }
    this.from = from;
}
// 定义子类
function Child(from){
    Parent.call(this,from);
    this.name = "child";
}

var f = function(){}; // 创建一个没有实例方法的类
f.prototype = Parent.prototype; // 浅拷贝父类原型 
Child.prototype = new f(); // 实例化f,此时没有实例化方法调用,同时将原型链建立
Child.prototype.construce = Child;

var child = new Child("child"); // 实例化子类
child.say(); // child
console.log(child.from); // child

特点

  • 比较完善

不足

  • 相对比较复杂

参考

https://www.jianshu.com/p/b76ddb68df0e
https://www.cnblogs.com/ranyonsue/p/11201730.html
https://www.cnblogs.com/humin/p/4556820.html#!comments

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐