1.原型链继承:可以继承属性和方法,但是会对原型上的方法误修改:
例如:继承属性
//父类
function Person(){
this.head = 'aaa';
}
//子类
function Student(s){
this.s = s;
}
Student.prototype = new Person();
var stu1 = new Student(1);
console.log(stu1.head) //aaa
stu1.head = 'bbb';
console.log(stu1.head)//bbb
var stu2 = new Student(1);
console.log(stu2.head)//aaa
打印出bbb的地方,是因为stu1.head自己添加了一个本地属性,而并不会影响原型上的属性
例如:原型链继承方法:
//父类
function Person(){
this.head = 'aaa';
this.love = ['我','爱','你'];
}
//子类
function Student(s){
this.s = s;
}
Student.protype = new Person();
var stu1 = new Student(1);
console.log(stu1.love);//我爱你
stu1.love.push('呀');
console.log(stu1.love);//我爱你呀
var stu2 = new Student(1);
console.log(stu2.love);//我爱你呀(这边并没有在本地修改,但是却对person里面的方法进行了修改)
2.借用构造函数继承
由于原型继承会对引用类型进行误修改,所以采用了构造函数继承方法,采用apply或call的形式
例如:
function Person(){
this.head = 'a';
this.fn = ['a','b','c'];
}
function Student(s){
this.s = s;
Person.call(this);
}
var stu1 = new Student(1);
console.log(stu1.fn);//'a','b','c'
stu1.fn.push('eeeeee');
console.log(stu1.fn);//'a','b','c','eeeeeee'
var stu2 = new Student(1);
console.log(stu2.fn); //'a','b','c','d'
Person.call(this),代表了把person构造函数借用给student函数,那么谁调用student,this就指向谁,因为创建了一个student实例,所以相当于Person.call(stu1),所以再修改就只是修改stu1这个实例对象,而不会影响其他
//缺点:这种形式的继承,每个子类实例都会拷贝一份父类构造函数的方法,作为实例自己的方法,占用
很多内存,而且当需求改变时,无法达到快速更新实例中的属性及方法
3.结合使用两种继承模式:
例如:
function Person(){
this.eat = function(){
this.head = 'aaa';
this.a = ['a','b','c'];
}
}
Person.prototype.eat = function(){
console.log('aaa');
}
Person.prototype.sleep = function(){
console.log('bbb');
}
function Student(id){
this.id = id;
Person.call(this);
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
var stu1 = new Student(1);
console.log(stu1.a);//a,b,c
stu1.a.push('d');
console.log(stu1.a)//a,b,c,d
var stu2 = new Student(1);
console.log(stu2.a);//a,b,c
stu1.eat();//aaa
stu2.sleep();//bbb
console.log(stu1.constructor); //student
其实还有一个拷贝的方法,也可以模拟继承:
总结一下:
原型链继承:是通过子类的原型等于父类的实例对象,从而继承父类原型中的方法及属性.
缺点是:如果修改子类的实例对象中的方法,父类中原型的方法以及属性(引用类型)也会随着修改
借用继承:是父类call或apply借用给子类,子类的实例可以继承父类的属性和方法
缺点是:每一次新的实例对象继承,都要再一次继承父类中的所有属性及方法,很耗费内存空间
组合继承:采用了原型链继承+借用继承,保证了子类实例可以继承父类原型中的属性和方法,然后根据本地修改,而不需要每一次都继承父类,然后又用了借用,这样修改实例就不会影响父类的原型了