javascript单例模式通过闭包封装私有实例变量,首次调用getinstance创建并缓存实例,后续调用直接返回该实例;支持带参初始化、重置销毁及es6模块化实现。

JavaScript 中可以用闭包封装私有状态,配合一个外部变量或内部缓存来确保只创建一次实例,从而实现单例模式。核心是:**利用闭包保存已创建的实例,后续调用直接返回它,不再新建**。
基础闭包单例(最简实现)
通过立即执行函数(IIFE)创建闭包,内部用变量 instance 缓存唯一实例:
const Singleton = (function() {
let instance = null;
function createInstance() {
return {
id: Date.now(),
sayHello() { return 'Hello from singleton!'; }
};
}
return {
getInstance() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
// 使用
const a = Singleton.getInstance();
const b = Singleton.getInstance();
console.log(a === b); // true
- 闭包内的
instance是私有变量,外部无法直接修改或重置 -
getInstance()每次都检查是否存在,不存在才初始化,保证唯一性 - 适合轻量、无构造参数、无需延迟初始化复杂逻辑的场景
支持构造参数的惰性单例
如果需要传参初始化(如配置对象),但又希望只初始化一次,可把参数缓存在首次调用时,并拒绝后续传参:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const ConfigurableSingleton = (function() {
let instance = null;
let initArgs = null;
function createInstance(config) {
return {
config: { ...config },
getVersion() { return this.config.version || '1.0'; }
};
}
return {
getInstance(config = {}) {
if (!instance) {
initArgs = config;
instance = createInstance(config);
} else if (Object.keys(config).length > 0) {
console.warn('Singleton already initialized; ignoring new config');
}
return instance;
}
};
})();
- 首次调用
getInstance({ version: '2.0' })才真正创建并记录配置 - 后续调用即使传参也不生效,避免误覆盖
- 也可改为抛错替代警告,增强约束力
带销毁/重置能力的可控单例
某些测试或插件场景需手动释放实例,可在闭包中暴露 reset 方法:
const ResettableSingleton = (function() {
let instance = null;
function createInstance() {
return {
data: [],
add(item) { this.data.push(item); }
};
}
return {
getInstance() {
if (!instance) {
instance = createInstance();
}
return instance;
},
reset() {
instance = null;
}
};
})();
// 使用示例
const s1 = ResettableSingleton.getInstance();
s1.add('a');
ResettableSingleton.reset();
const s2 = ResettableSingleton.getInstance();
console.log(s1 === s2); // false —— 新实例
-
reset()清空闭包内缓存,下次getInstance()将重新创建 - 注意:已持有的旧实例仍存在,只是不再被新调用返回
- 适用于模块热更新、单元测试隔离等需要控制生命周期的场景
ES6 模块 + 闭包(推荐现代写法)
用 ES6 模块天然的单例特性 + 闭包封装逻辑,更清晰且易维护:
// singleton.js
let instance = null;
class Database {
constructor(url) {
this.url = url;
this.connected = false;
}
connect() {
this.connected = true;
return 'Connected to ' + this.url;
}
}
export const getDatabase = (url = 'default.db') => {
if (!instance) {
instance = new Database(url);
}
return instance;
};
// 使用(任何地方 import 都共享同一份 instance)
// import { getDatabase } from './singleton.js';
// const db1 = getDatabase('prod.db');
// const db2 = getDatabase('test.db'); // 仍返回 prod.db 实例(因已存在)
- 模块顶层变量
instance在模块作用域内持久存在,等效于闭包私有变量 - 导出函数保持简洁,逻辑和状态分离明确
- 天然支持 tree-shaking 和模块化开发,比 IIFE 更符合现代工程实践
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










