JavaScript中常见的继承方式主要包括原型链继承、构造函数继承、组合继承、寄生组合继承、ES6类继承等,下面将详细介绍这些继承方式。
原型链继承
原型链继承是JavaScript中最为普遍的继承方式,它的基本思想是让一个构造函数的原型对象作为另一个构造函数的实例的原型,从而实现继承。其实现方式如下:
function Parent() {
this.name = 'parent';
}
Parent.prototype.sayName = function() {
console.log(this.name);
}
function Child() {
this.age = 18;
}
Child.prototype = new Parent();
var child1 = new Child();
child1.sayName(); // 输出 parent
console.log(child1.age); // 输出 18
上述代码中,定义了两个构造函数:Parent和Child。Parent定义了一个属性name和一个方法sayName,Child定义了一个属性age。使用Child.prototype = new Parent()
实现Child继承Parent的原型,从而实现原型链继承。
原型链继承的缺点是不能向Parent传递参数,因为在实例化的过程中,不能让子类的构造函数向Parent的构造函数传递参数。
构造函数继承
构造函数继承的基本思想是在子类构造函数的内部调用父类的构造函数。这种方式能够很好地解决原型链继承中子类实例可能会共享父类引用属性的问题,同时也能够实现向父类构造函数传递参数。其实现方式如下:
function Parent(name) {
this.name = name;
this.sayName = function() {
console.log(this.name);
}
}
function Child(name, age) {
Parent.call(this, name); // 调用父类构造函数
this.age = age;
}
var child1 = new Child('child', 18);
child1.sayName(); // 输出 child
console.log(child1.age); // 输出 18
上述代码中,定义了两个构造函数:Parent和Child。Parent定义了一个属性name和一个方法sayName,Child定义了一个属性age。在Child的构造函数中使用Parent.call(this, name)
调用父类构造函数加入子类实例,从而实现构造函数继承。
构造函数继承的缺点是不能继承父类的原型对象,从而不能复用父类方法。同时,由于每个实例都有一个父类构造函数的副本,因此在创建大量实例时会消耗大量内存。
组合继承
组合继承结合了原型链继承和构造函数继承的优点,将两者组合到了一起。其实现方式如下:
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log(this.name);
}
function Child(name, age) {
Parent.call(this, name); // 调用父类构造函数
this.age = age;
}
Child.prototype = new Parent(); // 继承父类的原型对象
Child.prototype.constructor = Child;
var child1 = new Child('child', 18);
child1.sayName(); // 输出 child
console.log(child1.age); // 输出 18
上述代码中,定义了两个构造函数:Parent和Child。Parent定义了一个属性name和一个方法sayName,Child定义了一个属性age。在Child的构造函数中使用Parent.call(this, name)
调用父类构造函数加入子类实例,使用Child.prototype = new Parent()
继承父类的原型对象,通过Child.prototype.constructor = Child
将原本指向Parent的Child.prototype.constructor指向Child本身,从而实现组合继承。
组合继承的优点是既能继承原型上的属性和方法,又能在创建实例的时候向父类传递参数。但是缺点是每次创建子类实例都要调用一次父类构造函数。
寄生组合继承
寄生组合继承是组合继承的一种优化,通过使用Object.create()方法代替new Parent()
来继承父类原型对象,从而避免了重复调用父类构造函数的问题。其实现方式如下:
function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log(this.name);
}
function Child(name, age) {
Parent.call(this, name); // 调用父类构造函数
this.age = age;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
var child1 = new Child('child', 18);
child1.sayName(); // 输出 child
console.log(child1.age); // 输出 18
上述代码中,定义了两个构造函数:Parent和Child。Parent定义了一个属性name和一个方法sayName,Child定义了一个属性age。在Child的构造函数中使用Parent.call(this, name)
调用父类构造函数加入子类实例,使用Child.prototype = Object.create(Parent.prototype)
来继承父类原型对象,通过Child.prototype.constructor = Child
将原本指向Parent的Child.prototype.construction指向Child本身,从而实现寄生组合继承。
ES6类继承
在ES6中,新增了类的概念,类似于其他语言。ES6通过class
关键字提供了类的声明方式,同时还新增了extends
和super
关键字来实现继承和调用父类的方法。其实现方式如下:
class Parent {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
class Child extends Parent {
constructor(name, age) {
super(name);
this.age = age;
}
}
var child1 = new Child('child', 18);
child1.sayName(); // 输出 child
console.log(child1.age); // 输出 18
上述代码中,使用class
关键字定义了两个类:Parent和Child。在Child中使用extends
关键字继承自Parent,使用super(name)
调用父类构造函数初始化子类实例,从而实现了ES6类继承。
需要注意的是,ES6类继承只是一种语法糖,在底层还是使用原型链实现的。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript中常见的继承方式总结 - Python技术站