Javascript 面向对象之继承
本文参考书籍<<Javascript高级程序设计>>
js继承方式:实现继承,主要依靠原型链实现。
原型链:基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法。
这里假设创建了一个Person构造函数和person1实例
构造函数、原型和实例的关系:每个构造函数都有一个原型对象(Person.prototype),原型对象都包含一个指向构造函数的指针(Person.prototype.constructor == Person),实例都包含一个指向原型对象的指针(person1.__proto__ == Person.prototype)。
如果,让一个原型对象等于另一个类型的实例,此时,原型对象将包含一个指向另一个原型的指针,另一个原型也包含着一个指向另一个构造函数的指针,以此类推,就构成了实例与原型的链条。
举例 说明:
本质:重写原型对象,代之以一个新类型的实例。
测试得出,此时,实例son1 的从属关系同时属于 Object,Parent,Son 三个对象,我们也发现,此时Son构造函数的constructor属性指向的是Parent,而不是Son。
如果,我们要重写父类中的某个方法,或要添加父类中不存在的某个方法,一定要在替换原型的语句之后。还要注意,在通过原型链实现继承时,不能使用对象字面量创建原型对象。因为这样做就会重写原型链。
原型链的问题:
引用类型的属性,会共享到所有依次对象创建的实例上。
对son1执行的修改,在son2中同样可以反映出来,显然,这不是我们想要的。
第二个问题就是,不能传递参数。
借用构造函数(伪造对象或经典继承):即在子类构造函数内部调用父类构造函数。
举例 说明:
通过call或apply,实际是在新创建的Son实例的环境下调用了Parent构造函数。
传递参数:子类构造函数中向父类构造函数传递参数。
借用构造函数问题:与单独使用构造函数创建对象一样,方法也将在构造函数内部定义。无法复用。且父类的原型上定义的方法,对于子类是不可见的。
小结:原型链继承,会造成实例共享引用类型且无法传参的问题,而借用构造函数继承,只能继承构造函数内部定义的信息,无法继承定义在原型上的属性和方法。
两者皆有缺点,但我们发现,如果,组合使用它们,就能完美解决各自的缺点,形成一种较为完美的继承方式。
组合继承(伪经典继承):基本思想:使用原型链实现对原型属性和方法的继承,使用构造函数实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又能保证每个实例都有自己的属性。
举例 说明:
原型式继承:基本思想:通过一个临时性的构造函数,作为中转,实现原型链的连接。
举例 说明:
此外,还有寄生式继承和寄生组合式继承,本文不做讨论。
ES6新增了Class继承方式,有时间学习后再来与大家分享!