JavaScript继承本质是基于原型的委托机制,对象通过[[Prototype]]链向上委托查找属性和方法;Object.create实现干净委托链,避免new Parent()副作用,ES6 class仍是语法糖,底层依赖原型委托。

JavaScript 的继承本质是基于原型的委托机制,不是传统类语言中的“复制”或“构造”,而是对象在查找属性或方法时,自动沿着 [[Prototype]] 链向上委托访问。实现委托式继承,关键在于正确建立原型链,并避免污染构造函数的 prototype 或误用 this。
用 Object.create 建立干净的原型委托链
这是最直接体现“委托”思想的方式:子类型对象的原型直接委托给父类型的原型对象,不调用父构造函数,也不混入实例属性。
示例:
<!-- 父类行为定义 -->
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log('I am ' + this.name);
};
<!-- 子类仅继承行为,不执行父构造逻辑 -->
function Dog(name, breed) {
this.name = name;
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; <!-- 修复 constructor 指向 -->
<!-- 可选择性地扩展子类方法 -->
Dog.prototype.bark = function() {
console.log('Woof! I am ' + this.name);
};
此时 new Dog('Leo', 'Golden') 调用 speak() 会委托到 Animal.prototype.speak,而 bark() 在自身原型上直接命中——这就是委托式继承的核心表现。
立即学习“Java免费学习笔记(深入)”;
避免 new Parent() 初始化子原型(防止意外副作用)
常见错误写法:Dog.prototype = new Animal(); —— 这会执行 Animal 构造函数,可能产生无意义实例、副作用(如发请求、修改全局状态),且无法传参定制父类初始化逻辑。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 用
Object.create(Parent.prototype)只建立委托关系,不触发构造 - 若需复用父类初始化逻辑,应在子构造函数中显式调用:
Animal.call(this, name) - 永远手动修复
constructor,否则dog.constructor === Animal会造成判断失真
ES6 class 是语法糖,底层仍是原型委托
class 和 extends 看似“类继承”,但编译后依然使用 Object.setPrototypeOf() 或 __proto__ 设置原型链。它只是让委托关系更声明式、更安全(如强制 super() 调用)。
等价写法:
class Animal {
constructor(name) { this.name = name; }
speak() { console.log('I am ' + this.name); }
}
class Dog extends Animal {
constructor(name, breed) {
super(name); <!-- 委托父构造,非继承 -->
this.breed = breed;
}
bark() { console.log('Woof!'); }
}
注意:extends 并未创建新副本,Dog.prototype.__proto__ === Animal.prototype 为 true,所有方法调用仍是委托查找。
组合委托:行为复用不依赖继承层级
真正符合委托精神的做法,是把可复用逻辑抽成纯对象,通过 Object.setPrototypeOf() 或 Object.assign() 动态挂载,而非强行拉长原型链。
例如共享工具方法:
const Flyable = {
fly() { console.log('Flying...'); }
};
function Bird(name) { this.name = name; }
Bird.prototype = Object.create(Animal.prototype);
Object.setPrototypeOf(Bird.prototype, Object.assign({}, Animal.prototype, Flyable));
<!-- 或更推荐:在实例上委托,如 this.fly = Flyable.fly.bind(this) -->
这种模式强调“对象需要什么能力,就委托给谁”,而不是“我属于哪个类”,更贴近原型设计本意。

















