从extend看JS继承
2023-10-17 21:24:10
继承是面向对象编程中最重要的概念之一,它允许我们创建新类,这些新类继承自现有类的属性和方法。在JavaScript中,继承可以通过多种方式实现,包括原型继承、组合继承和寄生继承。在本文中,我们将讨论这些不同的继承方式,并比较它们的优缺点。
首先,我们来谈谈原型继承。原型继承是JavaScript中最基本、最常见的继承方式。它允许我们通过创建一个新对象并将其原型对象设置为现有对象的来实现继承。例如,我们可以这样创建一个Person类:
function Person(name, age) {
this.name = name;
this.age = age;
}
// Person类的原型对象
Person.prototype.greet = function() {
console.log("Hello, my name is " + this.name + " and I am " + this.age + " years old.");
};
// 创建一个新的Person对象
const person = new Person("John Doe", 30);
// 调用原型对象中的greet方法
person.greet();
在这个例子中,我们创建了一个Person类,它有一个构造函数和一个原型对象。构造函数用于初始化对象的属性,而原型对象则用于定义对象的方法。当我们创建一个新的Person对象时,该对象的原型对象被设置为Person类的原型对象。这允许我们访问Person类的原型对象中的方法,例如greet方法。
原型继承的优点是简单易用。它不需要我们创建新的类,只需要将新对象的原型对象设置为现有对象的即可。但是,原型继承也有一个缺点,那就是它不能继承构造函数。这意味着子类不能使用父类的构造函数来初始化自己的属性。
为了解决原型继承的这个缺点,我们可以使用组合继承。组合继承允许我们继承构造函数和原型对象。它可以通过以下方式实现:
function Parent(name, age) {
this.name = name;
this.age = age;
}
Parent.prototype.greet = function() {
console.log("Hello, my name is " + this.name + " and I am " + this.age + " years old.");
};
function Child(name, age) {
// 调用父类的构造函数
Parent.call(this, name, age);
}
// 将子类的原型对象设置为父类的原型对象
Child.prototype = Object.create(Parent.prototype);
// 重新定义子类原型对象中的greet方法
Child.prototype.greet = function() {
console.log("Hello, my name is " + this.name + " and I am " + this.age + " years old. I am a child.");
};
// 创建一个新的Child对象
const child = new Child("John Doe", 30);
// 调用原型对象中的greet方法
child.greet();
在这个例子中,我们创建了一个Parent类和一个Child类。Parent类有一个构造函数和一个原型对象,Child类继承了Parent类的构造函数和原型对象。这意味着Child类可以访问Parent类的构造函数和原型对象中的方法。
组合继承的优点是可以继承构造函数和原型对象。但是,组合继承也有一个缺点,那就是它比较复杂。它需要我们创建新的类,并且需要使用Object.create()方法来设置子类的原型对象。
最后,我们来谈谈寄生继承。寄生继承允许我们通过创建一个新对象并将其原型对象设置为现有对象的来实现继承。但是,与原型继承不同的是,寄生继承不会创建新的类。它只是创建一个新对象并将其原型对象设置为现有对象的。例如,我们可以这样实现寄生继承:
function Parent(name, age) {
this.name = name;
this.age = age;
}
Parent.prototype.greet = function() {
console.log("Hello, my name is " + this.name + " and I am " + this.age + " years old.");
};
// 创建一个新的对象
const child = {};
// 将子对象的原型对象设置为父类的原型对象
child.__proto__ = Parent.prototype;
// 调用原型对象中的greet方法
child.greet();
在这个例子中,我们创建了一个Parent类和一个child对象。child对象没有构造函数,也没有原型对象。它只是通过将__proto__属性设置为Parent.prototype来继承Parent类的原型对象。这意味着child对象可以访问Parent类的原型对象中的方法。
寄生继承的优点是简单易用。它不需要我们创建新的类,只需要创建一个新对象并将其原型对象设置为现有对象的即可。但是,寄生继承也有一个缺点,那就是它不能继承构造函数。这意味着子对象不能使用父类的构造函数来初始化自己的属性。
综上所述,JavaScript中有三种继承方式:原型继承、组合继承和寄生继承。原型继承是最简单易用的,但它不能继承构造函数。组合继承可以继承构造函数和原型对象,但它比较复杂。寄生继承可以继承原型对象,但它不能继承构造函数。