可通过手动设置prototype和__proto__模拟原型链继承,核心是让子类实例沿__proto__访问父类原型方法;需用Object.create建立干净原型链、修复constructor、在子构造函数中借用父构造函数继承实例属性。

可以通过手动设置构造函数的 prototype 和实例的 __proto__(或用 Object.setPrototypeOf())来模拟原型链继承,核心是让子类实例能沿着 __proto__ 一路向上访问到父类原型上的方法和属性。
1. 基础原型链关系的手动构建
先明确原型链的本质:每个对象内部都有一个隐式原型 __proto__,它指向其构造函数的 prototype;而函数对象本身有 prototype 属性,用于被新实例继承。
例如,模拟 Animal → Dog 的继承:
// 父构造函数
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.__proto__ === Animal.prototype
Dog.prototype = Object.create(Animal.prototype);
// 修复 constructor 指向
Dog.prototype.constructor = Dog;
// 添加子类特有方法
Dog.prototype.bark = function() {
console.log(this.name + ' barks loudly');
};
// 测试
const myDog = new Dog('Max', 'Golden Retriever');
myDog.speak(); // Max makes a sound(来自 Animal.prototype)
myDog.bark(); // Max barks loudly(来自 Dog.prototype)
2. 不用 class、不用 extends,纯手写“寄生组合式继承”
这是最接近 ES6 class 继承行为的手写方案,避免了传统组合继承中父类构造函数被调用两次的问题。
关键三步:
- 用
Object.create(Parent.prototype)创建干净的子类原型对象(不执行父类构造函数) - 把子类原型的
constructor指回子类函数 - 在子类构造函数中用
Parent.call(this, ...)继承实例属性
3. 用 Object.setPrototypeOf 模拟动态原型链修改
适用于运行时动态改变继承关系(较少用,但有助于理解 __proto__ 的作用):
function A() {}
A.prototype.a = () => 'from A';
function B() {}
B.prototype.b = () => 'from B';
const obj = new B();
console.log(obj.b()); // 'from B'
console.log(obj.a()); // TypeError: obj.a is not a function
// 手动挂上 A.prototype
Object.setPrototypeOf(obj, A.prototype);
console.log(obj.a()); // 'from A'
console.log(obj.b()); // TypeError: obj.b is not a function(原 B.prototype 断开了)
注意:Object.setPrototypeOf 会替换整个 __proto__,不是叠加。要叠加需用 Object.create 构建中间原型链。
4. 小心陷阱:constructor 和 instanceof 的一致性
手写时容易忽略 constructor 指向被改写的问题,影响 instanceof 判断和代码可读性:
- 直接赋值
Dog.prototype = Animal.prototype❌ —— 会污染父类原型,且myDog.constructor === Animal - 正确做法是
Dog.prototype = Object.create(Animal.prototype)✅,再显式赋值constructor - 验证:
myDog instanceof Dog和myDog instanceof Animal都应为true
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











