全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-16 8 分钟 ✍️ juanwangdev

JavaScript 原型链继承

原型链继承是通过将子类原型指向父类实例实现的,是最基本的 JavaScript 继承模式。

基本实现

JavaScript
// 父类
function Animal(name) {
    this.name = name;
    this.colors = ['white', 'black'];  // 引用类型属性
}
Animal.prototype.sayName = function() {
    console.log('My name is ' + this.name);
};

// 子类:原型链继承
function Dog(name, breed) {
    this.breed = breed;
}
Dog.prototype = new Animal('Dog');  // 子类原型指向父类实例
Dog.prototype.constructor = Dog;   // 修复 constructor

// 使用
const dog1 = new Dog('Buddy', 'Golden');
const dog2 = new Dog('Max', 'Labrador');

dog1.sayName();  // 'My name is Dog'
console.log(dog1.breed);  // 'Golden'

继承原理

JavaScript
// 原型链结构
// Dog.prototype = new Animal('Dog')
// 意味着:
// dog.__proto__ → Dog.prototype(Animal实例) → Animal.prototype → Object.prototype

const dog = new Dog('Buddy', 'Golden');

console.log(dog.__proto__ === Dog.prototype);                // true
console.log(Dog.prototype.__proto__ === Animal.prototype);    // true
console.log(Animal.prototype.__proto__ === Object.prototype); // true

// dog 可以访问 Animal.prototype 上的方法
dog.sayName();  // 来自 Animal.prototype

引用类型共享问题

JavaScript
// 原型链继承的核心缺陷
function Animal(name) {
    this.colors = ['white', 'black'];  // 引用类型
}
Animal.prototype.sayName = function() {};

function Dog() {}
Dog.prototype = new Animal('Dog');

const dog1 = new Dog();
const dog2 = new Dog();

// 引用类型属性被所有实例共享
dog1.colors.push('brown');
console.log(dog2.colors);  // ['white', 'black', 'brown']  // 被污染!

// 解决方案:在子类构造函数中调用父类构造函数
function Dog(name) {
    Animal.call(this, name);  // 借用构造函数(组合继承)
    this.type = 'dog';
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

const dog1 = new Dog('Buddy');
const dog2 = new Dog('Max');
dog1.colors.push('brown');
console.log(dog2.colors);  // ['white', 'black']  // 独立

无法向父类传参

JavaScript
// 原型链继承:子类原型创建时无法动态传参
function Animal(name) {
    this.name = name;
}

function Dog() {}
Dog.prototype = new Animal();  // 无法根据 Dog 实例传 name

const dog = new Dog();
console.log(dog.name);  // undefined 或固定值

// 改进:组合继承
function Dog(name, breed) {
    Animal.call(this, name);  // 第一次调用父类
    this.breed = breed;
}
Dog.prototype = new Animal();  // 第二次调用父类(冗余)
Dog.prototype.constructor = Dog;

const dog = new Dog('Buddy', 'Golden');
console.log(dog.name);    // 'Buddy'
console.log(dog.breed);   // 'Golden'

方法重写

JavaScript
function Animal(name) {
    this.name = name;
}
Animal.prototype.speak = function() {
    console.log('Animal speaks');
};

function Dog(name) {
    this.name = name;
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

// 子类重写父类方法
Dog.prototype.speak = function() {
    console.log(this.name + ' barks');
};

// 添加子类特有方法
Dog.prototype.fetch = function() {
    console.log(this.name + ' fetches');
};

const dog = new Dog('Buddy');
dog.speak();  // 'Buddy barks'(重写方法)
dog.fetch();  // 'Buddy fetches'(特有方法)

寄生组合式继承(最优方案)

JavaScript
// 解决组合继承的两次调用问题
function inherit(Child, Parent) {
    // 创建中介原型,避免调用父类构造函数
    const prototype = Object.create(Parent.prototype);
    prototype.constructor = Child;
    Child.prototype = prototype;
}

function Animal(name) {
    this.name = name;
    this.colors = ['white'];
}
Animal.prototype.speak = function() {
    console.log(this.name + ' speaks');
};

function Dog(name, breed) {
    Animal.call(this, name);  // 只调用一次父类
    this.breed = breed;
}
inherit(Dog, Animal);  // 寄生组合继承

const dog1 = new Dog('Buddy', 'Golden');
const dog2 = new Dog('Max', 'Labrador');

dog1.colors.push('brown');
console.log(dog2.colors);  // ['white']  // 独立

dog1.speak();  // 'Buddy speaks'
console.log(dog1 instanceof Dog);    // true
console.log(dog1 instanceof Animal); // true

原型链继承对比

继承方式引用类型共享向父类传参父类调用次数
原型链继承有问题不支持1次
借用构造函数无问题支持每次实例化
组合继承无问题支持2次(冗余)
寄生组合继承无问题支持1次(最优)

注意事项

  • 原型链继承会导致引用类型属性被所有实例共享
  • 无法在创建子类实例时向父类构造函数传参
  • 推荐使用寄生组合式继承作为最优方案
  • 重写原型后必须修复 constructor
JavaScript
// 原型链继承适用场景
// 仅继承方法,父类没有引用类型属性
function Parent() {}
Parent.prototype.method = function() {};

function Child() {}
Child.prototype = new Parent();  // 可以使用

要点总结

  • 原型链继承:子类原型指向父类实例
  • 核心缺陷:引用类型属性被所有子类实例共享
  • 无法在实例化时向父类传参
  • 实际开发推荐寄生组合式继承(Object.create + 借用构造函数)
  • 重写原型后需修复 constructor
  • 判断继承关系:instanceofisPrototypeOf

📝 发现内容有误?点击此处直接编辑

← 上一篇 JavaScript 原型链基础
下一篇 → JavaScript 构造函数与原型
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库