javascript-----继承

(一)原型链继承
原理:是利用原型让一个引用类型继承另一个引用类型的属性和方法

function Cat(){
     this.category='我是猫科'
 }
 Cat.prototype.getCategory=function(){
     return this.category
 }

 function Tiger(){
     this.name = '大老虎'
 }

 Tigger.prototype = new Cat()
 Tigger.prototype.getName=function(){
     return this.name
 }

 var instace = new Tiger()
 // 在实现继承之后,通过Tiger创建的实例,既有Tiger的方法与属性,又有Cat的方法与属性
 console.log('我是'+instace.getName()+',我来自'+instace.getCategory())

以上代码定义了两个类型:Cat和 Tiger。每个类型分别有一个属性和一个方法。在这里Tiger继承了 Cat,而继承是通过创建 Cat的实例,并将该实例赋给Tiger.prototype 实现的。实现的本质是重写原型对象,原来存在于 Cat的实例中的所有属性和方法,现在也存在于 Tiger.prototype 中了。
原型链继承存在的问题:(1)所有实例共享原型,那么当其中一个实例改变了共享的属性,那么其余实例上对应的属性也被更改(2)在创建子类型的实例时,不能向超类型的构造函数中传递参数
总结:实践中很少会单独使用原型链

(二)借用构造函数(伪造对象或经典继承)
基本实现思想:在子类型构造函数的内部调用超类型构造函数

function Cat(){
   this.colos=['red','blue','yellow']
}
function Tiger(){
	 //继承了Cat,通过使用 apply()和 call()方法也可以在(将来)新创建的对象上执行构造函数
    Cat.call(this)
}
var instance1 = new Tiger()
instance1.colos.push('wwww')

var instace2 = new Tiger()

console.log(instace2.colos)  // ["red", "blue", "yellow"]

相对于原型链而言,借用构造函数可以在子类型构造函数中向超类型构造函数传递参数

function Cat(name){
     this.name = name
 }
 function Tiger(){
     // 继承同时传参
     Cat.call(this,'ccc')
     // 实例属性
     this.age = 15
 }
 var instace2 = new Tiger()
 
 console.log(instace2.name,instace2.age)  //ccc 15

借用构造函数存在的问题是:如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题——方法都在构造函数中定义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的(即父类原型链上的方法与属性在这种方式实现的时候,子类继承不了),结果所有类型都只能使用构造函数模式。
总结:借用构造函数的技术也是很少单独使用的
(三)组合继承
基本实现思想:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性

function Cat(name){
    this.name = name
     this.color=['red','yellow','block']
 }
 Cat.prototype.asyName=function(){
     console.log('我是猫科动物'+this.name)
 }
 function Tiger(name,age){
     // 继承属性
     Cat.call(this,name) //第二次调用 Cat() ,在新对象上创建了实例属性 name 和 color
     this.age = age
 }
 // 继承方法
 Tiger.prototype = new Cat()  //第一次调用 Cat() ,Tiger.prototype 会得到两个属性:name 和 color
 Tiger.prototype.constructor = Tiger
 Tiger.prototype.sayAge=function(){
     console.log(this.age)
 }

 var ins1 = new Tiger('ccc',18)
 ins1.color.push('mmm')
 console.log(ins1.color)
 ins1.asyName()
 ins1.sayAge()
 
 console.log('*****************')
 var ins2 = new Tiger('ddd',15)
 console.log(ins2.color)
 ins2.asyName()

总结:JavaScript 中最常用的继承模式
组合继承在实现的时候,初始化了两次父类构造函数,那么可以进行优化,

 	 //优化前部分代码
     Tiger.prototype = new Cat() 
      //优化后部分代码
     Tiger.prototype = Cat.prototype 

还有一个问题就是通过组合继承实现的继承,子类并没有办法区分是继承原型还是继承于构造函数,如何优化?
通过Object.create()

      //优化后部分代码
     Tiger.prototype = Object.create(Cat.prototype )
     Tiger.prototype.constructor = Tiger

(四)原型式继承

function object(o){
    // 在 object()函数内部,先创建了一个临时性的构造函数
    function F(){}
    // 传入的对象作为这个构造函数的原型
    F.prototype = o
    // 返回临时类型的一个新实例
    return new F()
}

object()对传入其中的对象执行了一次浅复制。ECMAScript 5 通过新增 Object.create()方法规范化了原型式继承。这个方法接收两个参数:一个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。在传入一个参数的情况Object.create()与 object()方法的行为相同
总结:只想让一个对象与另一个对象保持类似的情况下,原型式继承是完全可以胜任的。但是包含引用类型值的属性始终都会共享相应的值,就像使用原型模式一样。
(五)寄生式继承

(六)寄生组合式继承
组合继承最大的问题就是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部
基本实现思想:即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

function inheritPrototype(subType, superType){
     var prototype = object(superType.prototype); //创建对象
     prototype.constructor = subType; //增强对象
     subType.prototype = prototype; //指定对象
} 

实现一个简单的寄生组合继承

function object(o){
    // 在 object()函数内部,先创建了一个临时性的构造函数
    function F(){}
    // 传入的对象作为这个构造函数的原型
    F.prototype = o
    // 返回临时类型的一个新实例
    return new F()
}
function inheritPrototype(subType, superType){
    var prototype = object(superType.prototype); //创建对象
    prototype.constructor = subType; //增强对象
    subType.prototype = prototype; //指定对象
} 
function Cat(name){
    this.name = name
    this.color=[1,2,3]
}
Cat.prototype.sayName = function(){
    console.log('我是猫科动物'+this.name)
}

function Tiger(name,age){
    Cat.call(this,name)
    this.age = age
}
inheritPrototype(Tiger,Cat)
Tiger.prototype.sayAge = function(){
    console.log('我的年龄是'+this.age)
}

var ins1 = new Tiger('ccc',18)
ins1.sayName()
ins1.sayAge()

高效率体现在只调用了一次 Cat构造函数

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值