1.原型链继承
//原型对象上的属性和方法都能被实例对象共享
function Animal(){
this.name = 'ale';
this.color=['red','yellow'];
};
Animal.prototype.sayName=function (){
return this.name;
};
function Dog () {
};
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
var d1=new Dog();
console.log(d1.name); //打印ale
console.log(d1.sayName);//打印出函数
d1.color.push('blue');
console.log(d1.color); //打印(3) ["red", "yellow", "blue"]
console.log(d1.color); //打印(3) ["red", "yellow", "blue"]
//问题:1.不能传参 2.父类中的属性和方法一旦赋值给子类的原型属性,这些父类的属性和方法都属于子类的共享属性,修改引用类型的数据会影响所有子实例的值
2.借用构造函数继承
解决原型对象中包含引用类型值所带来问题
//在子类的构造函数内部中调用父类的构造函数
function Animal(name){
this.name = name;
this.color=['red','yellow'];
};
Animal.prototype.sayName=function (name){
return this.name;
};
function Dog (name) {
Animal.call(this,name)
};
var d1 = new Dog('lll');
var d2 = new Dog('555');
d1.color.push('blue');
console.log(d1.color);//(3) ["red", "yellow", "blue"]
console.log(d1.name);//lll
console.log(d2.color);//(2) ["red", "yellow"]
console.log(d2.name);//555
console.log(d1.sayName);//undefined
缺点:不能继承父类的原型对象上的方法
解决的方法–组合继承
function Animal(name){
this.name = name;
this.color=['red','yellow'];
};
Animal.prototype.sayName=function (name){
return this.name;
};
function Dog (name) {
//让父类的属性值继承下来,修改父类的引用类型的值,不会影响其他实例的引用类型的值
Animal.call(this,name)
};
//重写原型对象,把父类共享的方法继承下来
Dog.prototype = new Animal();
Dog.prototype.constructor=Dog;
var d1 = new Dog('lll');
var d2 = new Dog('555');
d1.color.push('blue');
console.log(d1.color); //打印出(3) ["red", "yellow", "blue"]
console.log(d1.name); //打印出lll
console.log(d2.color); //打印出(2) ["red", "yellow"]
console.log(d2.name); //打印出555
console.log(d1.sayName); //打印出ƒ(name){return this.name;}
//问题:会调用父类构造函数2次
**
寄生组合式继承方式
**
```css
function Animal(name){
this.name = name;
this.color=['red','yellow'];
};
Animal.prototype.sayName=function (name){
return this.name;
};
function Dog (name) {
//让父类的属性值继承下来,修改父类的引用类型的值,不会影响其他实例的引用类型的值
Animal.call(this,name)
};
//重写原型对象,把父类共享的方法继承下来
Dog.prototype = Object.create(Anmail.prototype) //解决了组合方式重复访问父类构造函数
Dog.prototype.constructor=Dog;
var d1 = new Dog('lll');
var d2 = new Dog('555');
d1.color.push('blue');
console.log(d1.color); //打印出(3) ["red", "yellow", "blue"]
console.log(d1.name); //打印出lll
console.log(d2.color); //打印出(2) ["red", "yellow"]
console.log(d2.name); //打印出555
console.log(d1.sayName); //打印出ƒ(name){return this.name;}
**
5.多线继承
function Person(name){
this.name = name;
};
Person.prototype.sayName=function (name){
return this.name;
};
function Parent(age){
this.age= age;
};
Parent.prototype.sayAge=function (age){
return this.age;
};
function Me(name,age) {
Person.call(this,name);
Parent.call(this,age);
};
//重写原型对象,把父类共享的方法继承下来
Me.prototype = Object.create(Person.prototype) //解决了组合方式重复访问父类构造函数
Me.prototype.constructor = Me;
Object.assign(Me.prototype ,Parent.prototype )//把Parent.prototype的方法复制到Me.prototype,防止重复复制导致覆盖
var d1 = new Me('ggd',28);
**特点和缺点总结:
1.原型链继承:
特点:重写了子类的原型对象,父类的原型对象上的属性和方法都被继承下来
缺点:父类上的所有属性和方法都被子类实例共享,一旦修改了引用类型的值,其他子类的实例的引用类型的值会被修改;当实例化子类的时候不能传递参数到父类
2.借用构造函数继承:
特点:通过子类函数内部调用父类的构造函数(call(),bind(),apply()),改变父类中的this指向
优点:把父类中的属性继承下来,还能够传参
缺点:父类的原型对象上的方法不能继承
3.组合是继承
特点:结合了原型链继承和借用构造函数继承的优点
原型链继承:父类的公有方法继承下来
借用构造函数继承:实例属性被子类继承下来
缺点:调用了2次父类构造函数
4.寄生组合式继承
原理:var Dog.prototype=Object.create(Anmail.prototyope)
把父类的的原型对象赋给子类的原型对象