只是想写一写原型链原型链~~~
继承
面向对象编程都支持两种继承:接口继承和实现继承。ECMAScript唯一支持的继承方法是实现继承,主要是通过原型链实现的。
什么是继承?
简单定义一下:对象A通过继承对象B,就能够直接拥有对象B所有属性和方法
继承有什么用?
我工作的时候几乎没有用到过继承。因为我用的框架主要是Vue,在页面级的开始中很少用到 js 继承方式,直接写个函数更简单高效些。
继承应用的最好是那些以js为主开发的大型项目,比如写js框架,前台所有东西的都用js来完成,整个站的跳转、部分逻辑、数据处理等大部分都是用js来做,这样的面向对象编程才有存在的价值和意义。
为什么要继承:通常在一般的项目里不需要,因为应用简单,但要用纯js做一些复杂的工具或框架系统就要用到了,比如webgis、或者js框架如jquery、ext什么的,不然一个几千行的框架不用继承得写很多代码,且维护艰难
原型链
ECMA-262把原型链定义为ECMAScript的主要继承方式。基本思想是通过原型继承多个引用类型的属性和方法。
构造函数、原型与实例的关系:每一个构造函数都有一个原型对象prototype
,原型对象有一个属性constructor
指回构造函数,实例有一个内部指针__proto__
指向原型对象。
提问:如果原型是另外一个类型的实例呢?
回答:这意味中这个原型本身有一个内部指针指向另一个原型,相应地另一个原型也有一个指针指向另一个构造函数。这样就在实例和实例之间构造了一条原型链。
实现原型链代码:
function SuperType(){
this.property = 'haha'
}
SuperType.prototype.getSuperValue = function(){
return this.property
}
function SubType(){
this.subProperty = 'xixi'
}
SubType.prototype = new SuperType()
SubType.prototype.getSubValue = function(){
return this.subProperty
}
let instance = new SubType()
盗用构造函数(对象伪装 / 经典继承)
解决什么问题:解决原型中引用值导致的问题
使用:在子类构造函数中调用父类构造函数
function SuperType(){
this.colors = ['red','blue','yellow']
}
function SubType(){
SuperType.call(this)
}
let instance1 = new SubType()
instance1.colors.push('green')
console.log(instance1) //['red','blue','yellow','green']
let instance2 = new SubType()
console.log(instance2) //['red','blue','yellow']
存在问题:不具备继承性,没有形成原型链,只是简单调用了父类构造函数,子类也不能访问父类原型上定义的方法。
组合继承
解决什么问题:解决盗用构造函数中不具备继承性的问题
使用:使用原型链继承原型上的属性和方法,通过构造函数继承实例属性,弥补了原型链和盗用构造函数的不足,是JavaScript中使用最多的继承模式。
function SuperType(name){
this.name = name
this.colors = ['red','blue','yellow']
}
SuperType.prototype.sayName = function(){
console.log(this.name)
}
function SubType(name,age){
SuperType.call(this,name)
this.age = age
}
SubType.prototype = new SuperType()
SubType.prototype.sayAge = function(){
console.log(this.age)
}
存在问题:存在效率问题,因为父类构造函数始终会被调用两次
原型式继承
解决什么问题:适合不需要单独创建构造函数,但仍然需要在对象间共享信息的场合
使用:代码如下,与ES 6新增的Object.assign()
功能一致,有子类原型 === 父类原型
function object(o){
function F(){}
F.prototype = o
return new F()
}
注意点:属性中包含的引用值始终会在相关对象中共享,与原型模式是一样的
寄生式继承
解决什么问题:无
使用:与原型式继承类似,创建一个实现继承的函数,以某种方式增强对象
function createAnother(original){
let clone = object(original) //调用函数创造一个新对象
clone.sayHi = function(){ //以某种方式增强这个对象
console.log('hi')
}
return clone
}
存在问题:无继承性
寄生式组合继承
解决什么问题:解决组合继承中的效率问题
使用:不通过父类构造函数给子类原型赋值,而是取得父类原型的一个副本
function inheritPrototype(subType,superType){
let prototype = Object(superType.prototype) //创建父类原型副本
prototype.constructor = subType //原型副本设置子类为构造器
subType.prototype = prototype //子类原型设置为父类原型副本
}
存在问题:还行吧,也就这样
后续会继续补充关于class的继承以及setPrototypeOf等继承的方法
参考链接
JavaScript高级程序设计第四版
https://www.cnblogs.com/yunshangwuyou/p/11968539.html