返回

JS实现继承——组合继承的替代品

前端


实现继承是JS中一个经久不衰的话题,为了更好理解组合继承,我们首先需要理解原型继承。
在JavaScript中,每一个函数都有一个prototype属性,指向创建该函数的构造函数的原型对象。

当通过构造函数创建新对象时,新对象会继承该构造函数的prototype的属性和方法。

原型继承的主要优点是实现简单,并且在许多情况下是足够的。然而,在某些情况下,我们可能需要更多的灵活性。例如,我们可能希望能够向父类构造函数传递参数。

组合继承是一种实现继承的常用方法,它是通过将原型继承和构造函数继承相结合来实现的。在组合继承中,我们首先通过原型继承创建子类,然后通过构造函数继承将父类的属性和方法拷贝到子类。

组合继承可以很好地解决原型继承的局限性,但它也存在一些问题。例如,组合继承会多次创建新的对象,这可能导致性能问题。此外,组合继承在语法上也比较晦涩,对于初学者来说可能难以理解。

所以我们这里引入组合继承的替代品——真正的继承。
与组合继承相比,真正的继承更简单、更易于理解,并且可以向父类构造函数传递参数。

为了实现真正的继承,我们需要使用Object.create()方法。Object.create()方法可以创建一个新对象,该对象继承自另一个对象。

现在,我们可以使用Object.create()方法来实现真正的继承:

function Parent(name) {
  this.name = name;
}

Parent.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name}.`);
};

function Child(name, age) {
  // 使用Object.create()创建一个新对象,该对象继承自Parent.prototype
  this.__proto__ = Object.create(Parent.prototype);

  // 向父类构造函数传递参数
  Parent.call(this, name);

  // 定义子类的属性和方法
  this.age = age;
}

// 继承父类原型中的greet方法
Child.prototype = Parent.prototype;

const child = new Child('John', 25);

child.greet(); // Hello, my name is John.
console.log(child.age); // 25

在上面的示例中,我们首先定义了一个Parent类。Parent类有name属性和greet方法。

然后,我们定义了一个Child类。Child类继承自Parent类,但它还有额外的age属性。

在Child类的构造函数中,我们使用Object.create()方法创建一个新对象,该对象继承自Parent.prototype。然后,我们向Parent构造函数传递参数,以便将name属性设置到子类对象中。

最后,我们使用Child.prototype = Parent.prototype来继承父类原型中的greet方法。

这样,我们就实现了真正的继承。现在,我们可以通过child.greet()来输出"Hello, my name is John.",通过child.age来输出25。

真正的继承更加灵活、强大,并且在语法上更加清晰易懂。因此,在大多数情况下,我们应该使用真正的继承来实现继承,而不是组合继承。