原型链继承

  1. function Animal() {
  2. this.colors = ['yellow','red'];
  3. }
  4. Animal.prototype.getColor = function () {
  5. return this.colors;
  6. };
  7. function Dog() {}
  8. Dog.prototype = new Animal();
  9. let dog1 = new Dog();
  10. dog1.colors.push('green');
  11. let dog2 = new Dog();
  12. console.log(dog2.colors); // ['yellow','red', 'green']

原型链继承存在的问题:

  • 原型中包含的引用类型属性将被所有实例共享
  • 子类的实例化的时候不能给父类构造函数传参

借用构造函数实现继承

  1. function Animal(name) {
  2. this.name = name;
  3. this.colors = ['yellow','red'];
  4. this.getName = function () {
  5. return this.name;
  6. }
  7. }
  8. function Dog(name) {
  9. Animal.call(this, name);
  10. }
  11. Dog.prototype = new Animal();
  12. let dog1 = new Dog('dog1');
  13. dog1.colors.push('green');
  14. let dog2 = new Dog('dog2');
  15. console.log(dog2.colors); // ['yellow','red']

借用构造函数实现继承解决了原型链继承的2个问题:引用类型共享问题以及传参问题。但是由于方法必须定义在构造函数中,所以会导致每次创建子类实例都会创建一遍方法。

组合继承

组合继承结合了原型链和借用构造函数,将两者的优点集中了起来。基本的思路是使用原型链继承原型上的属性和方法,而通过借用构造函数继承实例属性。这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性。

  1. function Animal(name) {
  2. this.name = name;
  3. this.colors = ['yellow','red'];
  4. }
  5. Animal.prototype.getName = function(){
  6. return this.name;
  7. };
  8. function Dog(name,age) {
  9. Animal.call(this, name);
  10. this.age = age;
  11. }
  12. Dog.prototype = new Animal();
  13. Dog.prototype.constructor = Dog;
  14. let dog1 = new Dog('dog1',11);
  15. dog1.colors.push('green');
  16. let dog2 = new Dog('dog2',22);
  17. console.log(dog2);

寄生式组合继承

组合继承已经相对完善了,但是还存在问题,它的问题就是调养了 2 次父类构造函数,第一次是在 new Animal(),第二次是在 Animal.call();
所以解决方案就是不直接调用父类构造函数给子类原型复制,而是通过创建空函数 F 获取父类原型的副本。

  1. // old
  2. Dog.prototype = new Animal();
  3. Dog.prototype.constructor = Dog;
  4. // new
  5. function F() {}
  6. F.prototype = Animal.prototype;
  7. let f = new F();
  8. f.constructor = Dog;
  9. Dog.prototype = f;

class 实现继承

  1. class Animal {
  2. constructor(name) {
  3. this.name = name;
  4. }
  5. getName() {
  6. return this.name;
  7. }
  8. }
  9. class Dog extends Animal{
  10. constructor(name,age){
  11. super(name);
  12. this.age = age;
  13. }
  14. }