简单了解一下JavaScript原型链

只是想写一写原型链原型链~~~

继承

面向对象编程都支持两种继承:接口继承和实现继承。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

猜你喜欢

转载自blog.csdn.net/weixin_42060560/article/details/110439459