原型链继承通过子构造函数.prototype=new父构造函数实现,核心缺陷有三:①引用类型属性被所有实例共享;②无法向父构造函数传参;③子实例无法拥有独立的父类实例属性。

JavaScript 原型链继承是通过让子构造函数的 prototype 指向父构造函数的一个实例来实现的。它不靠“类”或关键字,而是靠对象内部的 [[Prototype]] 链自然向上查找属性和方法——这是 JS 原生、底层的继承机制。
怎么实现原型链继承
核心就三步:
- 定义父构造函数,并把共用方法挂到它的 prototype 上
- 定义子构造函数,不做特殊处理(先不调用父类)
- 关键操作:子构造函数.prototype = new 父构造函数()
例如:
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(this.name + ' makes a sound');
};
function Dog(name, breed) {
this.breed = breed;
}
Dog.prototype = new Animal(); // ← 这一步建立原型链
Dog.prototype.constructor = Dog; // ← 修复 constructor 指向(否则会指向 Animal)
const dog = new Dog('Max', 'Husky');
dog.speak(); // "Max makes a sound"
致命缺陷一:引用类型属性被所有实例共享
因为 Dog.prototype 是 new Animal() 的一个实例,而这个实例里的引用值(如数组、对象)会被所有 Dog 实例通过原型链访问到——改一个,全跟着变。
比如:
function Animal() {
this.hobbies = ['sleep', 'eat'];
}
function Dog() {}
Dog.prototype = new Animal();
const d1 = new Dog();
const d2 = new Dog();
d1.hobbies.push('bark');
console.log(d2.hobbies); // ['sleep', 'eat', 'bark'] ← 不合理!
这不是“继承”,是“共用一份内存”。对状态型数据极其危险。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
致命缺陷二:无法向父构造函数传参
在 Dog.prototype = new Animal() 这行里,你没法给 Animal 传参。哪怕 Animal 需要初始化 name 或 id,你也只能写死或留空。
比如你想让每个 Dog 实例自动带上 Animal 的默认 name,但又想让子类自己控制 name 值——原型链继承做不到这点,因为 new Animal() 发生在子类定义阶段,不是实例化阶段。
致命缺陷三:子类无法访问父类构造函数中的实例属性
如果父构造函数里用了 this.xxx = ... 定义了实例属性(非 prototype 上的方法),这些属性只属于 那个 new 出来的原型对象,而不是每个子实例自己独有的。
换句话说:子实例读得到,但改不了自己的副本——改的是原型上的那一份,影响所有兄弟实例。
这和我们期望的“每个对象独立拥有父类状态”完全相悖。
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










