详解JS六大继承

一、 原型链继承

方法:通过将子类型的显示原型prototype的值作为超类型(父类型)的实例,然后通过原型链去访问

function Supertype()//超类型
{
   /..../
}
function Subtype()//子类型
{
/../
}
Subtype.prototype=new Supertype();//继承
Supertype.prototype.constructor=Subtype;//将constructor指回


如图
在这里插入图片描述
优点:大家可以共用超类型原型中的方法,不会造成内存的浪费
缺点:
1、由于子类型的显示原型是超类型的实例,故超类型中的属性会被访问,如果你不希望继承超类型的显示原型中的属性时,这种方法不太好
2、而且在当属性是引用类型时,所有的实例会共用一个引用类型
3、无法给超类型传递参数

二、借用构造函数去继承

该方法主要是借用apply和call方法在其他子构造函数中引用超类型构造函数

function Supertype(name,age)
{
this.name=name;
this.age=age;
}
function Subtype(other)
{
this.other=other;
Supertype.call(this,"小明","小红","小白");
}

优点:解决了原型链继承的无法给超类型传递参数的缺点
缺点:仅仅借用构造函数,无法解决构造函数的一个问题,即所有方法都在构造函数中定义,在创建实例时大家都有各自的方法但确实同一个作用,造成了大量内存空间的浪费

三、组合继承

组合继承即是将原型链继承和借用构造函数去继承两种方法结合,用借用构造函数来给超类型构造函数传递参数,然后用原型链模型实现方法的复用。

function Supertype()//超类型
{
   /..../
}
function Subtype()//子类型
{
/../
Supertype(call,this);
}
Subtype.prototype=new Supertype();//继承
Supertype.prototype.constructor=Subtype;//将constructor指回

结合了原型链继承和借用构造函数去继承的优点,成为JS最常用的继承方法

四、原型式继承

原型式继承:
原型式继承的的实现方法与普通继承的实现方法不同,原型式继承并没有使用严格意义上的构造函数,而是借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

function object(o)
{
function F(){};
F.prototype=o;
return new F();
}
var obj={//将对象作为超类型
...
}
var sub=object();

现在可以使用object.create()方法来创建原型式继承。这个方法传入两个参数,第一个参数是用作新对象原型的对象,第二个参数是其他额外属性对象。
你可能觉得这种方法和原型链继承很想,但具体来说,他们的原理都是通过原型链去实现继承,不同点在于这种方法主要是运用在两个对象之间,在没有必要兴师动众创建构造函数,而只想让一个对象与另一个对象保持类似的情况,就可以用原型式继承。

五、寄生式继承

寄生式继承与原型式继承是一种紧密相关的思路,可以理解为在原型式继承的基础上,在通过某些方式来增强这个对象。

function createOther(obj)
{
var clone=object(obj);
clone.method=function()//增强对象
{
...
}
return clone;
}

可以看到区别就在于寄生式继承就是在原型是继承的基础上增加一些新功能,值得注意的是,我们这里用了上面的object方法,但这只是一个实例,任何返回一个对象的函数都可以在这里使用。
缺点:这种方法的缺点是用这种方法创建的对象会由于不能做到函数复用而降低效率

六、寄生组合式继承

引用JS高级程序设计中的描述,我觉得讲的很详细:前面说过,组合继承是JavaScript 最常用的继承模式;不过,它也有自己的不足。组合继承最大的
问题就是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是
在子类型构造函数内部。没错,子类型最终会包含超类型对象的全部实例属性,但我们不得不在调用子
类型构造函数时重写这些属性。再来看一看下面组合继承的例子。
function SuperType(name){
this.name = name;
this.colors = [“red”, “blue”, “green”];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
SuperType.call(this, name); //第二次调用SuperType()
this.age = age;
}
SubType.prototype = new SuperType(); //第一次调用SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
};
加粗字体的行中是调用SuperType 构造函数的代码。在第一次调用SuperType 构造函数时,
SubType.prototype 会得到两个属性:name 和colors;它们都是SuperType 的实例属性,只不过
现在位于SubType 的原型中。当调用SubType 构造函数时,又会调用一次SuperType 构造函数,这
一次又在新对象上创建了实例属性name 和colors。于是,这两个属性就屏蔽了原型中的两个同名属
性。图6-6 展示了上述过程。
如图6-6 所示,有两组name 和colors 属性:一组在实例上,一组在SubType 原型中。这就是调
用两次SuperType 构造函数的结果。好在我们已经找到了解决这个问题方法——寄生组合式继承。
所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背
后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型
原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型
的原型。寄生组合式继承的基本模式如下所示。
function inheritPrototype(subType, superType){
var prototype = object(superType.prototype); //创建对象
prototype.constructor = subType; //增强对象
subType.prototype = prototype; //指定对象
}
这个示例中的inheritPrototype()函数实现了寄生组合式继承的最简单形式。这个函数接收两
个参数:子类型构造函数和超类型构造函数。在函数内部,第一步是创建超类型原型的一个副本。第二
步是为创建的副本添加constructor 属性,从而弥补因重写原型而失去的默认的constructor 属性。
最后一步,将新创建的对象(即副本)赋值给子类型的原型。这样,我们就可以用调用inherit-
Prototype()函数的语句,去替换前面例子中为子类型原型赋值的语句了,例如

function SuperType(name){
this.name = name;
this.colors = [“red”, “blue”, “green”];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
alert(this.age);
};

这个例子的高效率体现在它只调用了一次SuperType 构造函数,并且因此避免了在SubType.
prototype 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;因此,还能够正常使用
instanceof 和isPrototypeOf()。开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。
总结:就是该方法想直接用绿色的线代替子类型到父类型的原型过程中多走的子类型原型
在这里插入图片描述

7、关系总结

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值