javascript通过原型链实现继承,核心是__proto__或prototype指向父对象以委托查找;常用object.create(parent.prototype)设置子类原型并修复constructor;class extends是语法糖,底层仍操作原型链;需避免原型上定义可变属性导致共享问题。

JavaScript 中通过原型链实现对象间属性继承,核心是让一个对象的 __proto__(或构造函数的 prototype)指向另一个对象,从而在属性查找时沿链向上委托。
构造函数 + prototype 实现继承
这是最经典的方式:子构造函数的 prototype 指向父构造函数的一个实例(或直接设置为父类的 prototype),使子类实例能访问父类原型上的方法和属性。
- 用
Object.create(Parent.prototype)设置子类原型,避免调用父构造函数初始化实例属性 - 重设子类
constructor指回自身,否则会指向父构造函数 - 示例:
function Animal(name) { this.name = name; }
Animal.prototype.speak = function() { console.log(this.name + ' makes a sound'); };
function Dog(name, breed) {
Animal.call(this, name); // 借用构造函数继承实例属性
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype); // 建立原型链
Dog.prototype.constructor = Dog; // 修复 constructor
const dog = new Dog('Leo', 'Golden');
dog.speak(); // Leo makes a sound → 成功继承原型方法
Object.setPrototypeOf() 动态设置原型
适用于已有对象,想临时或运行时改变其原型链。它直接修改对象的内部 [[Prototype]]。
- 第一个参数是目标对象,第二个是新的原型对象
- 不推荐在性能敏感场景频繁使用,可能影响引擎优化
- 示例:
const animal = { speak() { console.log('Generic sound'); } };
const dog = { name: 'Buddy' };
Object.setPrototypeOf(dog, animal);
dog.speak(); // Buddy 继承了 animal 的 speak 方法
ES6 class 语法糖下的原型链本质
class 和 extends 是对原型继承的封装,底层仍是操作 prototype 和 __proto__。
-
class B extends A会让B.prototype.__proto__ === A.prototype -
super()在子类构造器中等价于Animal.call(this, ...) - 静态方法继承通过
B.__proto__ === A实现(即构造函数本身也形成原型链)
注意事项与常见陷阱
原型链继承不是“复制”,而是“委托访问”。所有实例共享原型上的引用类型属性,容易引发意外修改。
- 不要在父类
prototype上定义可变对象(如数组、对象),否则所有子实例共用同一份 - 只继承方法和不可变属性;实例独有数据必须在构造函数内初始化(配合
call/apply) - 检查属性是否来自原型链可用
hasOwnProperty()或Object.prototype.hasOwnProperty.call(obj, key)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











