js实现继承的方法

1、原型链继承

2、构造函数继承

3、组合继承

4、原型式继承

5、寄生式继承

6、寄生组合式继承

一、原型链继承

1实现原型链的一种基本模式
 

function SuperType(){
this. property = true;
SuperType . prototype. getSuperValue = function(){
return this.property;};
function SubType(){
this. subproperty = false;}

//继承,用SuperType类型的一个实例来重写SubType 类型的原型对象
SubType.prototype = new SuperType();
SubType.prototype.getSubValue =function(){
return this .subproperty;};
var instance = new SubType();
alert(instance . getSuperValue());//true

其中,SubType继承了SuperType,而继承是通过创建SuperType 的实例,并将该实例赋值给SubType的原型实现的。

实现的本质是重写子类型的原型对象,代之以一个新类型的实例。子类型的新原型对象中有一个内部属性'Prototype指向了SuperType 的原型,还有一个从SuperType原型中继承过来的属性constructor指向了SuperType 构造函数。

最终的原型链是这样的:“instance 指向SubType的原型,SubType 的原型又指向SuperType的原型,SuperType 的原型又指向Object的原型(所有函数的默认原型都是Object的实例,因此默认原型都会包含一个内部指针,指向Objet.prototype)

原型链的缺点:

1、在通过原型来实现继承时,原型实际上会变成另一个类型的实例。于是,原先的实例属性也就顺理成章地变成了现在的原型属性,并且会被所有的实例共享。这样理解:在超类型构造函数中定义的引|用类型值的实例属性,会在子类型原型上变成原型属性被所有子类型实例所共享
2、在创建子类型的实例时,不能向超类型的构造函数中传递参数
2、借用构造函数继承(也称伪造对象或经典继承)

//在子类型构造函数的内部调用超类型构造函数:使用apply() 或call()方法将父function SuperType(){
//定义引用类型值属性
this.colors = ["red","green" , "blue"];}
function SubType(){
//继承SuperType, 在这里还可以给超类型构造函数传参
SuperType. call(this);}
var instance1 = new SubType();
instance1. colors . push("purp1e");
alert(instance1. colors);// "red, green, blue, purple"
var instance2 = new SubType();
alert(instance2. colors);// "red, green, blue"

         通过使用apply0或call)方法,我们实际上是在将要创建的SubType实例的环境下调用了SuperType 构造函数。这样一来,就会在新SubType对象上执
          行SuperType()函数中定义的所有对象初始化代码。结果SubType的每个实例就都会具有自己的colors属性的副本了
          借用构造函数的优点是解决了原型链实现继承存在的两个问题
          借用构造函数的缺点是方法都在构造函数中定义,因此函数复用就无法实现了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式.

 3、组合继承(也称伪经典继承)

/1将原型链和借用构造函数的技术组合到一块。使用原型链实现对原型属性和方法的继承,而通过构造函数来实现对实例属性的继承,这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有自己的属性;
function SuperType(name){
this .name = name;
this.colors = ["red" ,"green","blue"];}
SuperType . prototype. sayName = function(){
alert(this .name);};
function SubType(name,age){
//借用构造函数方式继承属性
SuperType. call(this , name);
this.age = age;}
//原型链方式继承方法
SubType.prototype = new SuperType();
SubType .prototype . constructor = SubType;
SubTypeprototype. sayAge = function(){
alert(this.age);
var instancel = new SubType("1uochen",22);
instance1. colors . push("purp1e");
alert(instance1 . colors);// "red, green,blue, purple"
instancel. sayName();
instance1. sayAge();
var instance2 = new SubType("tom" ,34);
alert(instance2.colors);// "red, green,blue"
instance2. sayName();
instance2. sayAge();

       组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为javascript中最常用的继承模式。而且,使用instanceof操作符和isPrototype0方法也能够用于识别基于组合继承创建的对象。

       但它也有自己的不足无论在什么情况下, 都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另-次是在子类型构造函数内部。
4.原型式继承

//借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
1、自定义一个函数来实现原型式继承
function object(o){
function F(){}
F. prototype = o;
return new F();

在object(函数内部,先创建一个临时性的构造函数, 然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。实质上,object() 对传入其中的对象执行了一次浅复制.

使用Object.reate0方法实现原型式继承

这个方法接收两个参数: 一是用作新对象原型的对象和一一个为新对象定义额外属性的对象。在传入一个参数的情况下,此方法与object)方法作用一致。在传入第二个参数的情况下,指定的任何属性都会覆盖原型对象上的同名属性。

var person = {
name: ” luochen",
colors: ["red","green","blue"]};
var anotherPerson1 = Obiect create(person, {
name: {
value: "tom"
});
var anotherPerson2 = object.create(person,{
name:{value: "jerry"
}
});
anotherPerson1 colors . push("purple");
alert(anotherPerson1. name);// "tom"
alert(anotherPerson2. name);// "jerry"
alert (anotherPerson1. colors);//"red,green,blue, purple"
alert(anotherPerson2 . colors);//"red,green,bule, purple";

只是想让一个对象与另一个对象类似的情况下,原型式继承是完全可以胜任的。但是缺点是:包含引用类型值的属性始终都会共享相应的值

5、寄生式继承

//创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回这个对象
function createPerson(original){
var clone= object. create(original);//通过object. creat()函数创建一个新对象
clone . sayGood = function(){//增强这个对象
alert("helloworld1! !");}
return clone;//返回这个对象
}

       在主要考虑对象而不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式。此模式的缺点是做不到函数复用
6、寄生组合式继承

//通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型.
function SuperType(name){
this. name= name;
this. colors = ["red","green","blue'"];
SuperType . prototype . sayName = function(){
alert(this . name);
};
function SubType(name, age){
SuperType.call(this , name);
this.age = age;
}
//创建超类型原型的一个副本
var anotherPrototype = Object. create(SuperType . prototype);
//重设因重写原型而失去的默认的constructor 属性
anotherPrototype. constructor = SubType;
//将新创建的对象赋值给子类型的原型
SubType . prototype = anotherPrototype;
SubType . prototype.sayAge = function(){
alert(this.age);};
var instancel = new SubType("luochen" ,22);
instance1. colors . push("purple");
alert( instance1. colors);// "red, green, blue, purple"
instance1. sayName();
instance1. sayAge();
var instance2 = new SubType("tom" ,34);
alert(instance2.colors);//"red, green, blue" !instance2. sayName();
instance2. sayAge();

这个例子的高效率体现在它只调用一次SuperType构造函数,并且因此避免了在SubType.prototype上面创建不必要,多余的属性。与此同时,原型链还能保持不变;因此还能够正常使用instance操作符和isPrototype0方法
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值