1. 原型链继承
- 方法
我们知道构造函数、原型对象和实例的关系:每个构造函数都有一个原型对象,原型对象(.prototype
)的constructor
属性指向构造函数,而实例的__proto__
指向构造函数的原型对象(可以参考文章 原型链)。
那么,如果让原型对象等于另一个对象的实例的话,这时原型对象的constructor
属性指向另一个对象,原型对象的__proto__
指向另一个对象的原型对象。 - 举例
function SuperType(name) {
this.name = name; }
SuperType.prototype.getName = function() {
return this.name; };
function SubType(age) {
this.age = age; }
//原型链继承SuperType
SubType.prototype = new SuperType('super');//继承了SuperType的所有属性和方法
SubType.prototype.getAge = function (){
return this.age; };//为SubType添加新方法
var sub1 = new SubType(10); //实例化SubType
console.log(sub1.getName());//super
console.log(sub1.getAge());//10
其中,前几行代码可以看作通过组合使用原型模式和构造函数模式创建对象的过程,只不过这个对象是已经存在的 SubType.prototype
,也就是重写了子类型的原型对象。创建对象的方法进 JS创建对象
function SuperType() {
this.name ='super'; }
SuperType.prototype.getName = function() {
return this.name; };
SubType.prototype = new SuperType();
所以,原型链继承的本质就是将SubType
的原型重写为SuperType
的实例,这时,SubType
的原型不仅具有作为一个 SuperType
的实例所拥有的全部属性和方法, 而且其内部的__proto__
指向了 SuperType
的原型。最终结果就是:sub1
指向 SubType
的原型,SubType
的原型又指向 SuperType
的原型。
console.log(sub1.constructor = SubType.prototype.constructor === SuperType);//true,注意这一点
console.log(SubType.prototype.__proto__ === SuperType.prototype);//true
注意,此时instance.SuperType
为SuperType
,因为SubType.prototype
被重写为了
SuperType
的实例化对象,而这个对象的constructor
为SuperType
。如下图所示
- 优点
容易实现,父类新增原型属性和方法,子类都能访问到 - 缺点
(1) 原型属性在所有实例中是共享的
function SuperType() {
this.name='Super';
this.colors = ["red", "blue", "green"];
}
function SubType(){
}
//继承了 SuperType
SubType.prototype = new SuperType();
var sub1 = new SubType();
var sub2 = new SubType();
sub1.name = 'sub1';
sub1.colors.push("black");
console