原型链不直接实现单例模式,但通过将方法挂载在prototype上可提升单例复用性与轻量性;构造函数仅初始化状态,方法统一定义在原型,推荐ES模块导出实例并结合class语法,避免手动操作__proto__。

原型链本身不直接用于实现单例模式,但它能间接提升单例对象的复用性与轻量性——关键在于:单例应尽量避免冗余构造逻辑,而原型链天然支持方法共享,让实例共用一套行为定义,减少内存开销。
用原型链优化单例对象的方法复用
当单例是一个“带行为的对象”(比如日志器、事件总线),把方法挂载在原型上,比每次在实例上重复定义更高效。虽然单例只存在一个实例,但统一使用原型可保持设计一致性,也为未来可能的扩展(如 mock 或继承)留出空间。
- 构造函数中只初始化状态属性(如
logCount、cache = new Map()) - 所有方法(
log()、emit()、setItem())定义在prototype上 - 确保单例工厂(如
getInstance())返回的是该构造函数的实例,而非字面量对象
避免原型污染,保持单例纯净
单例常被全局访问,若误将方法或属性直接加到 Object.prototype 或构造函数的 prototype 上(尤其在多人协作时),可能引发意外覆盖或冲突。要特别注意:
- 不要在运行时动态修改内置对象原型(如
Array.prototype.pushSingleton) - 若需扩展,优先用组合(composition)而非修改原型;例如给单例加工具方法,直接挂到实例自身或用独立工具模块
- ES6 class 写法下,方法默认在原型上,这是安全且推荐的方式
结合模块系统,让原型链“隐式生效”
现代项目中,真正高效的做法是:用 ES 模块导出一个已实例化的对象,它天然单例;再通过类定义 + 原型方法组织逻辑。这样既免去 getInstance() 的调用成本,又保留原型带来的方法共享优势。
立即学习“Java免费学习笔记(深入)”;
- 写一个
Logger类,方法全在prototype上 - 在模块顶层
export const logger = new Logger() - 其他文件
import { logger }—— 所有导入都指向同一对象,其原型链也完全一致 - 无需手动管理实例,也不破坏原型结构
慎用 __proto__ 手动链接做单例
有人尝试用 Object.setPrototypeOf(instance, Singleton.prototype) 动态挂原型,这不仅可读性差,还可能绕过 class 初始化逻辑,导致 this 绑定异常或私有字段不可见。这不是设计技巧,而是隐患。
- 构造函数或 class 是原型链建立的正当入口,应始终通过
new或工厂函数创建实例 - 单例的“唯一性”靠控制创建逻辑(如静态检查、闭包缓存)保证,不是靠后期修补原型
- 手动操作
__proto__在严格模式下已被弃用,应避免


















