JavaScript原型复用核心是“一份方法、多个实例共享”,通过[[Prototype]]链指向同一原型对象实现;常用方式包括构造函数prototype挂载、Object.create显式继承、call/apply/bind临时借用及Mixin模式组合行为。

JavaScript 中原型对象实现方法复用,核心在于“一份方法、多个实例共享”,而不是每个对象都存一份副本。这靠的是每个实例内部的 [[Prototype]] 链接指向同一个原型对象,调用方法时自动向上查找。
把方法挂到构造函数的 prototype 上
这是最常用也最直接的方式。方法只定义一次,所有通过该构造函数创建的实例都能访问它,且共用同一函数引用:
- 构造函数内部定义的属性(如
this.name)属于实例私有 - 而
Constructor.prototype.xxx = function(){...}定义的方法,会被所有实例通过原型链访问 - 调用时
this仍指向调用它的那个实例,能正常读取实例自己的属性
例如:
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
return `${this.name} makes a sound`;
};
const dog = new Animal('Dog');
const cat = new Animal('Cat');
console.log(dog.speak === cat.speak); // true —— 同一个函数,内存只占一份
用 Object.create 显式以对象为原型
当不需要构造函数、只想让一个对象复用另一个对象的方法时,Object.create() 是更轻量的选择:
立即学习“Java免费学习笔记(深入)”;
- 它直接创建一个新对象,并将其 [[Prototype]] 指向指定对象
- 被指定的对象就成了“行为模板”,它的方法可被新对象直接继承使用
- 适合纯数据对象之间的委托复用,比如配置对象、工具对象的扩展
例如:
const baseTool = {
log: function(msg) { console.log('[tool]', msg); },
delay: function(ms) { return new Promise(r => setTimeout(r, ms)); }
};
const myTool = Object.create(baseTool);
myTool.log('ready'); // ✅ 可用
console.log(myTool.__proto__ === baseTool); // true
通过 call/apply/bind 借用方法(不依赖原型链)
有时候你并不想建立长期的原型关系,只是临时让某个对象“用一下”别的对象的方法。这时可以跳过原型链,直接调用:
-
Array.prototype.slice.call(arrayLike)就是经典例子:类数组对象没有slice,但借用 Array 原型上的方法来处理自己 - 本质是改变函数执行时的
this指向,让它临时绑定到目标对象上 - 适用于跨类型复用(如让对象借用数组方法)、或避免污染原型的场景
组合多个行为:Mixin 模式
JavaScript 不支持多重继承,但可以用 mixin 把多个原型上的方法“复制”到一个目标原型上,实现行为聚合:
- 遍历源对象(或其 prototype)的可枚举方法,逐个赋值给目标对象的 prototype
- 目标实例就能同时使用多个来源的方法,看起来像“继承了多个父类”
- 注意命名冲突和
instanceof失效问题,适合功能模块化复用
例如:
function mix(target, ...sources) {
sources.forEach(src => {
Object.getOwnPropertyNames(src.prototype).forEach(key => {
if (key !== 'constructor') {
target.prototype[key] = src.prototype[key];
}
});
});
}
// 使用
mix(Child, Flyable, Swimmable); // Child.prototype 现在有了 fly() 和 swim()


















