原型继承与构造函数继承

109 阅读1分钟

原型继承与构造函数继承

原型链 Prototype Chaning

function Animal(){
    this.names = ['animal', 'zoom', 'beast', 'creature']
    this.say = function(index){
        console.log(`I am ${this.names[index]}`)
    }
}

var oneAnimal = new Animal()
oneAnimal.say(1) // I am zoom

每一个方法都有原型,我们可以在原型链挂载属性或者方法,原型在方法和通过new方法产生的实例之间分享:

function Animal(){
}
Animal.prototype.names = ['animal', 'zoom', 'beast', 'creature']
Animal.prototype.say = function(index){
    console.log(`I am ${this.names[index]}`)
}

var oneAnimal = new Animal()
oneAnimal.say(1) 
//> I am zoom

原型链最大的好处是实例间可以复用:

var anotherAnimal = new Animal()
anotherAnimal.say(2)
//> I am beast

接着说一下原型链是怎么继承的:

function Animal(){
}
Animal.prototype.names = ['animal', 'zoom', 'beast', 'creature']
Animal.prototype.say = function(index){
    console.log(`I am ${this.names[index]}`)
}

function Cat(){
    this.whiskers = 8
}

// 从Animal中继承
Cat.prototype = new Animal()

var kitten = new Cat()
kitten.say(2) //> I am beast

4 原型链有两个大问题,一个是引用值在实例之间互用:

var kitten = new Cat()
var oldCat = new Cat()
kitten.names.push('kitten')
oldCat.say(4) //> I am kitten

第二个问题是,在创建实例的时候,不能传参给父类构造器。

原型式继承 Prototypal Inheritance

在之前的例子中,我们需要先自定义一个Animal父类,然后再定义Cat子类去继承它,原型式继承的作用是跳过第一步,使用一个现成的类直接继承。

function create(fatherInstance){
    function Son(){}
    Son.prototype = fatherInstance
    return new Son()
}

这个就是原型式继承,Object.create()就是使用这种方式:

借用构造函数继承

这种技术的基本思想很简单,就是在子类型的构造函数中调用超类型构造函数。其代码演示如下:

function SuperType() {
    this.colors = ['red', 'blue', 'green']
}
function SubType() {
    //继承SuperType
    SuperType.call(this)
}
var instance1 = new SubType()
instance1.colors.push('black')
alert(instance1.colors) //red,blue,green,black

var instance2 = new SubType()
alert(instance2.colors) //red,blue,green 

相对于原型链而言,借用构造函数有一个很大的优势,就是在子类型构造函数中向超类型构造函数传递参数。但该方法也存在一个问题,函数服用无从谈起。