一.构造继承
构造函数继承:
function Super(){
this.colors= ['c','a','b'];
this.print = function(){
console.log(this.colors);
}
}
function Sub(){
Super.call(this);
}
var instance1 =new Sub();
instance1.colors.push('v');
console.log(instance1.colors); //c,a,b,v
var instance2 =new Sub();
console.log(instance2.colors);//c a b
基本思想 : 构造函数方式就是假借call和apply方法,把父类的构造函数嫁接到子类身上,子类new出一个实例的时候,就把父类的构造函数的内容copy到实例中了。
对于基本属性而言,非常棒,每个实例之间不共享属性,立刻拥有自己的私有属性了。对于方法属性而言,不太好。我原本希望实现1个函数在内存存储,最好没有拷贝,却能被父类和子类一起来共享。
实现了属性的私有,没有实现方法的共享。
解决了原型链的两大问题:
其一, 保证了原型链中引用类型值的独立,不再被所有实例共享;
其二, 子类型创建时也能够向父类型传递参数.
组合继承:
function Super(){
this.colors= ['c','a','b'];
}
Super.prototype.print= function(){
console.log(this.colors);
};
function Sub(){
Super.call(this);
}
Sub.prototype =new Super();
Sub.prototype.constructor= Sub;
var instance1 =new Sub();
instance1.colors.push('v');
console.log(instance1.colors); //a b c v
var instance2 =new Sub();
console.log(instance2.colors); //a b c
组合式继承采用了原型链式继承和构造函数式继承结合的办法。
我们把(我们希望子类有一份拷贝的)基本属性放在父类的构造函数里。我们把希望共享的函数方法放在父类的原型上。
实现了函数的共享,也实现了属性的私有。
原型继承
function Super(){
this.colors= ['c','a','b'];
this.print= function(){
console.log(this.colors);
}
}
function Sub(){
}
Sub.prototype =new Super();
var instance1 =new Sub();
instance1.colors.push('v');
console.log(instance1.colors); //c,a,b,v
var instance2 =new Sub();
console.log(instance2.colors);//c a b v
原型链式借用了js的对象的一个特性:对象去寻找自己的属性的时候,先在自己的当前对象上寻找,如果没有,就去自己的原型链上寻找,一直顺着原型链向上寻找直到找到null。
对于一个基本属性而言,这太尴尬了,子类修改了属性的值,父类和所有其他子类的值就全部被修改了。因为大家伙使用的是相同指针指向的堆上同一个值。
方法和属性全都被共享了。
寄生式继承
var sup = {
colors : ['c','a','b']
}
var instance1 =Object.create(sup);
instance1.colors.push('v');
console.log(instance1.colors); //a b c v
var instance2 =Object.create(sup);
console.log(instance2.colors); //a b c v
原来是一种变了花样的原型继承呀。
所以它有原型继承的所有缺点 :基本属性不能私有
还有所有优点:方法属性可以共享
不同点就是:我们不需要去创建函数来表示一个类(构造函数),通过类(构造函数)去创建一个对象。object.create里面就帮我们创建类(构造函数)了。我们在外面看,好像实现了object之间的直接继承。
寄生组合式继承
function Super(){
this.colors= ['c','a','b'];
}
Super.prototype.print= function(){
console.log(this.colors);
};
function Sub(){
Super.call(this);
}
var proto =Object.create(Super.prototype);
proto.constructor= Sub;
Sub.prototype =proto ;
var instance1 =new Sub();
instance1.colors.push('v');
console.log(instance1.colors);//a b c v
var instance2 =new Sub();
console.log(instance2.colors);//ab c
组合式并不完美啊。有一个很大的问题。基本属性在子类对象里出现了两次!!
Super.call(this);这个实现了对colors的拷贝。
var proto = Object.create(Super.prototype);
这句非常关键,我们只把super原型上的内容放在proto的原型链上了。
proto.constructor = Sub;Sub.prototype = proto ;
实现了原型和构造器的互相指引。
与组合式不通的就是寄生组合式更加关注了父类的基本类型不能被共享到原型链上,变成误用的代码,浪费内存。
寄生组合式继承,集寄生式继承和组合继承的优点于一身,是实现基于类型继承的最有效方法.