JavaScript作为一门基于原型的编程语言,本身没有传统面向对象语言的类继承语法,不过可以通过多种手段实现继承效果,满足代码复用和对象关系构建的需求。下面介绍几种常见的JavaScript继承实现方式。

原型链继承
原型链继承是JavaScript中最基础的继承方式,核心是利用原型链让一个引用类型继承另一个引用类型的属性和方法。
// 父类构造函数
function Parent() {
this.name = 'parent';
this.colors = ['red', 'blue'];
}
// 父类原型方法
Parent.prototype.getName = function() {
return this.name;
};
// 子类构造函数
function Child() {
this.age = 18;
}
// 将子类的原型指向父类的实例,实现原型链继承
Child.prototype = new Parent();
// 修正子类原型的构造函数指向
Child.prototype.constructor = Child;
// 子类原型方法
Child.prototype.getAge = function() {
return this.age;
};
// 测试
const child1 = new Child();
console.log(child1.getName()); // 输出 parent
console.log(child1.getAge()); // 输出 18
// 引用类型属性被所有实例共享的问题
child1.colors.push('green');
const child2 = new Child();
console.log(child2.colors); // 输出 ["red", "blue", "green"]这种方式的优点是简单易懂,能继承父类原型上的方法。缺点是父类实例的引用类型属性会被所有子类实例共享,并且创建子类实例时无法向父类构造函数传参。
构造函数继承
构造函数继承也叫经典继承,核心是在子类构造函数中调用父类构造函数,通过call或apply改变父类的this指向。
// 父类构造函数
function Parent(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
// 父类原型方法
Parent.prototype.getName = function() {
return this.name;
};
// 子类构造函数
function Child(name, age) {
// 调用父类构造函数,将this指向当前子类实例
Parent.call(this, name);
this.age = age;
}
// 测试
const child1 = new Child('child1', 18);
console.log(child1.name); // 输出 child1
console.log(child1.age); // 输出 18
child1.colors.push('green');
console.log(child1.colors); // 输出 ["red", "blue", "green"]
const child2 = new Child('child2', 20);
console.log(child2.colors); // 输出 ["red", "blue"] 不会互相影响
// 无法继承父类原型上的方法
console.log(child1.getName); // 输出 undefined这种方式的优点是可以向父类传参,子类实例不会共享父类的引用类型属性。缺点是无法继承父类原型上的方法,方法都在构造函数中定义,无法实现函数复用。
组合继承
组合继承是结合原型链继承和构造函数继承的优点,是最常用的继承方式之一。
// 父类构造函数
function Parent(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
// 父类原型方法
Parent.prototype.getName = function() {
return this.name;
};
// 子类构造函数
function Child(name, age) {
// 构造函数继承,继承父类实例属性
Parent.call(this, name);
this.age = age;
}
// 原型链继承,继承父类原型方法
Child.prototype = new Parent();
// 修正构造函数指向
Child.prototype.constructor = Child;
// 子类原型方法
Child.prototype.getAge = function() {
return this.age;
};
// 测试
const child1 = new Child('child1', 18);
console.log(child1.getName()); // 输出 child1
console.log(child1.getAge()); // 输出 18
child1.colors.push('green');
console.log(child1.colors); // 输出 ["red", "blue", "green"]
const child2 = new Child('child2', 20);
console.log(child2.colors); // 输出 ["red", "blue"]
console.log(child2.getName()); // 输出 child2这种方式的优点是既可以继承父类原型上的方法实现函数复用,又能保证每个子类实例有自己的属性,还能向父类传参。缺点是父类构造函数会被调用两次,一次是在创建子类原型时,一次是在子类构造函数中,存在一定的性能开销。
寄生组合式继承
寄生组合式继承是对组合继承的优化,解决了父类构造函数被调用两次的问题,是业界公认的最优继承方案。
// 父类构造函数
function Parent(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
// 父类原型方法
Parent.prototype.getName = function() {
return this.name;
};
// 寄生组合式继承的核心函数
function inheritPrototype(child, parent) {
// 创建父类原型的副本
const prototype = Object.create(parent.prototype);
// 修正副本的构造函数指向
prototype.constructor = child;
// 将子类的原型指向该副本
child.prototype = prototype;
}
// 子类构造函数
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
// 调用继承函数
inheritPrototype(Child, Parent);
// 子类原型方法
Child.prototype.getAge = function() {
return this.age;
};
// 测试
const child1 = new Child('child1', 18);
console.log(child1.getName()); // 输出 child1
console.log(child1.getAge()); // 输出 18
console.log(child1 instanceof Child); // 输出 true
console.log(child1 instanceof Parent); // 输出 true这种方式只调用了一次父类构造函数,并且避免了在子类原型上创建不必要的属性,同时还能保持原型链的正常结构,是使用最多的继承实现方式。
ES6 class继承
ES6引入了class语法,其底层的继承实现本质还是基于原型链,但是语法更加简洁清晰,更接近传统面向对象的继承写法。
// 父类
class Parent {
constructor(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
getName() {
return this.name;
}
}
// 子类,通过extends关键字继承父类
class Child extends Parent {
constructor(name, age) {
// 调用父类构造函数,必须在this之前调用
super(name);
this.age = age;
}
getAge() {
return this.age;
}
}
// 测试
const child1 = new Child('child1', 18);
console.log(child1.getName()); // 输出 child1
console.log(child1.getAge()); // 输出 18
child1.colors.push('green');
console.log(child1.colors); // 输出 ["red", "blue", "green"]
const child2 = new Child('child2', 20);
console.log(child2.colors); // 输出 ["red", "blue"]ES6的class继承语法糖让继承的写法更加直观,不需要手动处理原型链和构造函数指向,开发中如果使用现代JavaScript语法,优先选择这种方式实现继承。
JavaScript继承原型链构造函数组合继承修改时间:2026-06-06 07:39:16