1.原型链继承
基本思想是利用原型链让一个引用类型继承另一个引用类型的属性和方法。实际的实现方式就是让子类的原型指向父类的实例对象
function Animal() {
this.color='red'
this.play=['跑','跳','走']
}
function Dog() {
}
Dog.prototype=new Animal()
原型链继承的优点:
- 简单易于实现,父类的新增的实例与属性子类都能访问
原型链继承的缺点:
- 新实例无法向父类传参数,实际上应该说是没有办法在不影响所有实例对象的情况下给父类传参。
- 所有的新实例对象都是继承自父类的实例对象,一旦一个修改就会全部修改,如下例。
function Animal() {
this.color='red'
this.play=['跑','跳','走']
}
function Dog() {
}
Dog.prototype=new Animal()
let dog1=new Dog()
let dog2=new Dog()
dog1.play.push('吃')
console.log(dog1);
console.log(dog2);
2.借用构造函数
实际上就是在子类中通过call方法调用父类构造函数
function Animal() {
this.color='red'
this.play=['跑','跳','走']
}
function Dog() {
Animal.call(this)
}
let dog1=new Dog()
let dog2=new Dog()
dog1.play.push('吃')
console.log(dog1);
console.log(dog2);
借用构造函数的特点:
- 可通过call方法向父类传递参数。
- 只继承了父类构造函数的属性,没有继承父类原型的属性。
借用构造函数的缺点:
- 只能继承父类构造函数的属性
- 每一个实例中都有父类构造函数的属性,代码会臃肿。
3.组合继承
其思路是使用原型链实现对原型属性和方法的继承,而借助构造函数来实现对实例属性的继承。
function Animal(color) {
this.color=color
this.play=['跑','跳','走']
}
function Dog(color,age) {
Animal.call(this,color)
this.age=age
}
Dog.prototype=new Animal('black')
Dog.prototype.constructor=Dog
Dog.prototype.sayHello=function(){
console.log('Hello');
}
let dog1=new Dog('red',3)
let dog2=new Dog('blue',5)
dog1.play.push('吃')
console.log(dog1);
console.log(dog2);
组合继承的缺点:
- 调用了两次父类构造函数,造成内存上的浪费。
4.原型式继承
可以通过Object.create()方法实现新建一个对象,该对象的原型指向括号中的父类对象。如下例:注意dog1.name=‘dog1’这一句实际上是在定义dog1的内部属性而不是操作原型上的属性,后面的dog1.play.push('吃')才是在操作原型。
let dog={
name:'大黄',
age:3,
play:['跑','跳','走']
}
let dog1=Object.create(dog)
let dog2=Object.create(dog)
dog1.name='dog1'
dog1.play.push('吃')
console.log(dog);
console.log(dog1);
console.log(dog2);
缺点:原型上属性共用,一改俱改。
5.寄生式继承
与原型式继承原理基本一致,外边套了个壳子,可以写入自己想添加的新属性或者方法。
let dog={
name:'大黄',
age:3,
play:['跑','跳','走']
}
function jiSheng(obj) {
let clone=Object.create(obj)
clone.sayHello=function(){
console.log('Hello');
}
return clone
}
let dog1=jiSheng(dog)
let dog2=jiSheng(dog)
dog1.name='dog1'
dog1.play.push('吃')
console.log(dog);
console.log(dog1);
console.log(dog2);
6.寄生组合继承
所谓寄生组合继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。直白一点就是通过call来实现父类构造函数中的属性的继承,通过Object.create()来实现对父构造函数的原型的继承。
function Animal(color) {
this.color=color
this.play=['跑','跳','走']
}
Animal.prototype.sayHello=function(){
console.log('Hello');
}
function Dog(color,age) {
Animal.call(this,color)
this.age=age
}
Dog.prototype=Object.create(Animal.prototype)
let dog1=new Dog('red',3)
console.log(dog1);
优点:优化了组合继承中的对于父类构造函数内补属性继承时的臃肿,被认为是最理想的继承方式。
7.class继承
class Animal{
constructor(color){
this.color=color
this.play=['跑','跳','走']
}
sayHello(){
console.log('Hello');
}
}
class Dog extends Animal{
constructor(color,age){
super(color)
this.age=age
}
sayBye(){
console.log('Bye');
}
}
let dog1=new Dog('red',3)
console.log(dog1);