javascript用闭包实现单例模式的核心是:利用iife创建私有作用域,内部缓存instance变量,返回的函数首次调用时创建实例、后续直接返回缓存值,确保全局唯一且不可外部修改。

JavaScript 中用闭包实现单例模式,核心是利用闭包保存私有实例变量,确保全局仅创建一次对象,并提供统一访问入口。
闭包封装实例,防止外部直接 new
把单例实例定义在闭包内部,外部无法访问或修改它,只能通过返回的函数获取。这样既隐藏了实例,又避免重复初始化。
- 用立即执行函数(IIFE)创建作用域
- 在内部声明一个变量(如 instance)缓存实例
- 返回一个函数,首次调用时创建实例并赋值,之后直接返回缓存值
基础写法示例
以下是最简实现:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
const Singleton = (function() {
let instance = null;
return function() {
if (!instance) {
instance = {
data: Math.random(),
getName() { return 'Singleton'; }
};
}
return instance;
};
})();
// 使用
const a = Singleton();
const b = Singleton();
console.log(a === b); // true
支持传参的增强版
如果单例需要初始化参数(比如配置),可以在首次调用时接收并缓存,后续调用忽略参数:
- 判断 instance 是否已存在,存在则直接返回
- 不存在时,用传入参数构造实例(可配合 class 或工厂函数)
- 注意:不能让多次调用传不同参数导致行为不一致,通常只允许首次有效
结合 class 的常见实践
更现代的写法是把类和闭包结合,保持类的结构清晰:
class Logger {
constructor() {
this.logs = [];
}
log(msg) {
this.logs.push(`[${Date.now()}] ${msg}`);
}
}
const createLogger = (function() {
let instance;
return function() {
if (!instance) {
instance = new Logger();
}
return instance;
};
})();
const logger1 = createLogger();
const logger2 = createLogger();
console.log(logger1 === logger2); // true
这种写法兼顾可读性、封装性和复用性,是实际项目中较推荐的方式。不复杂但容易忽略细节——关键是闭包锁住变量,且 getInstance 函数始终引用同一份 instance。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










