单例原型模式指确保类唯一实例并复用原型方法:用静态属性或闭包控制实例唯一性,状态存实例、方法放原型,避免重复创建函数且防止共享数据污染。

单例原型模式在 JavaScript 中并不是一个标准术语,但通常指结合单例模式与原型链特性的实现方式:确保一个类只有一个实例,同时让该实例能通过原型继承共享方法,避免重复创建函数副本。
核心思路:用闭包或静态属性控制实例唯一性
JavaScript 中没有原生的“类单例”语法,需手动保证构造函数只返回同一个对象。关键在于——不每次都 new 出新对象,而是首次调用时创建,后续直接返回缓存实例。
- 使用构造函数内部的私有变量(闭包)保存实例,适合简单场景
- 在构造函数上挂载静态属性(如 instance),更直观且便于调试
- 原型上的方法不依赖实例状态时,可安全复用,天然支持“原型模式”的轻量特性
基础实现(静态属性 + 原型方法)
这是最常用、易理解的方式:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
function Logger() {
if (Logger.instance) {
return Logger.instance;
}
Logger.instance = this;
this.logs = [];
}
Logger.prototype.log = function(msg) {
this.logs.push(`[${new Date().toISOString()}] ${msg}`);
};
Logger.prototype.print = function() {
console.log(this.logs.join('\n'));
};
// 使用
const a = new Logger();
const b = new Logger();
console.log(a === b); // true
a.log('start');
b.log('done');
a.print(); // 两条日志都输出
```
更健壮的写法(防止绕过 new 调用)
上面的实现允许 Logger()(不带 new)导致 this 指向全局,出错。可加判断确保必须用 new:
- 检查
this instanceof Logger,不是则手动return new Logger() - 或用 ES6 class + static getter,语义更清晰
class Database {
constructor() {
if (Database.instance) {
return Database.instance;
}
Database.instance = this;
this.connected = false;
}
connect() {
if (!this.connected) {
this.connected = true;
console.log('Connected to DB');
}
}
}
// 可选:暴露统一入口
Database.getInstance = () => {
return Database.instance || new Database();
};
```
注意点:原型 vs 实例属性的分工
单例的核心是“状态唯一”,所以所有共享状态(如 logs、connected)必须放在实例上;而方法应放在原型上,否则每次 new 都会重复创建函数,失去原型优势。
- ✅ 正确:状态在实例(
this.xxx),行为在原型(Class.prototype.method) - ❌ 错误:把日志数组定义在原型上(
Logger.prototype.logs = []),会导致所有实例共用同一份数据,看似单例实则混乱 - ⚠️ 注意:箭头函数无法用作原型方法(没有自己的
this),也不适合需要访问实例状态的场景
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










