原型链继承借用构造函数继承(伪造对象、经典继承)实例继承(原型式继承)组合式继承寄生组合继承es6继承 extends
时间: 2025-03-01 20:45:09 浏览: 40
### JavaScript 继承模式详解
#### 一、原型链继承
在原型链继承中,子类通过设置其 `prototype` 属性指向父类的一个实例实现继承。这使得所有子类实例共享来自父类的方法和属性。
优点在于简单易懂;缺点则是所有子类实例都会共享同一份从父类继承来的数据成员,如果其中一个实例修改了这些共享的数据,则会影响到其他实例[^1]。
```javascript
function Parent() {
this.colors = ["red", "blue"];
}
Parent.prototype.getColor = function () {
return this.colors;
};
function Child() {}
Child.prototype = new Parent();
const child1 = new Child();
child1.colors.push('green');
console.log(child1.colors); // ['red', 'blue', 'green']
const child2 = new Child();
console.log(child2.colors); // ['red', 'blue', 'green']
```
#### 二、借用构造函数(经典继承)
此方法是在子类构造器内部调用超类构造器,并传入当前上下文(`this`)作为参数。这样可以解决上述提到的原型链继承中存在的问题——即每个新创建的对象都有自己独立的一套属性副本而不是引用同一个对象。
但是这样做也有局限性:无法访问到定义于父级原型上的任何方法或特性[^3]。
```javascript
function Parent(color) {
this.color = color;
}
// 定义一个非构造函数的方法
Parent.prototype.sayColor = function(){
console.log(this.color);
};
function Child(color){
Parent.call(this,color);
}
let c=new Child("yellow");
c.sayColor(); // Uncaught TypeError: c.sayColor is not a function
```
#### 三、组合式继承
为了克服前两种方式各自的不足之处,“组合式继承”应运而生。它结合了原型链与构造函数的优点,在初始化阶段利用后者复制必要的属性给新的实例,而在之后则依赖前者获取公共行为/功能。
不过这种做法存在一个小缺陷就是会在执行一次无意义的构造过程(当我们将父类实例赋值给孩子类的 prototype 的时候).
```javascript
function Parent(name) {
this.name = name || 'parent';
}
Parent.prototype.getName = function () {
return this.name;
};
function Child(name, age) {
Parent.call(this,name);
this.age=age||0;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var kid =new Child('kid',8);
console.log(kid.getName()); // kid
console.log(kid instanceof Child); // true
console.log(kid instanceof Parent); //true
```
#### 四、寄生组合式继承
该方案优化了传统意义上的组合继承,避免重复调用了父类构造器的问题。具体来说就是在建立子类原型的时候不再直接使用 `new Parent()` 而是借助辅助工具 Object.create 来完成这项工作,从而确保整个过程中仅发生过唯一一次对于基底构造者的实际调用操作[^2][^4].
```javascript
function inheritPrototype(subType, superType) {
const prototype = Object.create(superType.prototype); // 创建对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 指定对象
}
inheritPrototype(Child, Parent);
```
#### 五、ES6 Class 关键字下的继承机制
随着 ECMAScript 版本不断更新迭代至第六版以后引入的新语法糖——class 类声明语句以及相应的 extends 扩展关键字让开发者们得以更加直观简洁地表达面向对象编程思想下父子关系之间的联系形式。值得注意的是这里所谓的 class 并不是真正意义上实现了 Java 或 C++ 那样的静态类型检查支持而是基于现有 JS 动态特性的基础上做了一些封装处理而已.
```javascript
class Animal{
constructor(type){
this.type = type;
}
sayHi(){return `${this.type}: Hi!`}
}
class Dog extends Animal{
bark(){return `${this.type}: Woof woof!`}
}
let doggy = new Dog('dog');
console.log(doggy.sayHi()); // dog: Hi!
console.log(doggy.bark()); // dog: Woof woof!
```
阅读全文
相关推荐

















