JavaScript闭包单例模式通过IIFE封装私有instance变量,提供getInstance接口确保全局唯一实例;首次调用创建并缓存,后续返回同一对象,支持懒加载和参数初始化,适用于轻量工具类。

JavaScript中利用闭包实现单例模式,核心在于**用闭包封装私有实例变量,确保全局唯一访问入口**,避免污染全局命名空间,同时防止重复创建对象。
闭包封装实例,控制唯一性
通过立即执行函数(IIFE)创建闭包作用域,在其中声明一个私有变量保存实例。外部无法直接访问该变量,只能通过返回的函数接口获取实例。
- 每次调用 getInstance 时,先检查私有 instance 是否已存在;若不存在,则 new 一次并缓存
- 后续调用直接返回缓存的实例,保证内存中仅有一个对象
- 构造函数可接受参数,但首次初始化后的参数将被忽略(或按需设计为允许重置)
基础实现示例
以下是一个简洁、可复用的闭包单例封装方式:
const Singleton = (function() {
let instance = null;
function createInstance() {
return {
data: Math.random(),
getName() { return 'Singleton Instance'; }
};
}
return {
getInstance() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
// 使用
const a = Singleton.getInstance();
const b = Singleton.getInstance();
console.log(a === b); // true
支持构造参数与延迟初始化
实际项目中常需传参初始化,且希望真正用到时才创建(懒汉式)。可在 getInstance 中接收参数,并在首次调用时完成初始化逻辑:
立即学习“Java免费学习笔记(深入)”;
- 首次调用 getInstance({ name: 'A' }) 时创建带配置的实例
- 后续调用即使传不同参数,也只返回首次创建的实例(保持单例语义)
- 如需强制重置,可额外暴露 clearInstance 方法(谨慎使用)
注意事项与适用场景
闭包单例适合轻量级工具类、状态管理器、日志记录器等无需复杂生命周期控制的模块。
- 不适用于需要多实例配置差异大的场景(此时应改用工厂模式)
- 注意闭包长期持有实例可能导致内存无法释放,尤其在 SPA 中需评估销毁时机
- ES6 模块本身具有单例特性(import 多次仍为同一模块对象),简单场景下可优先使用模块导出代替手写单例











