JavaScript单例模式用闭包封装唯一实例,通过返回函数实现懒加载与全局访问,确保instance私有且仅初始化一次;但返回对象非类实例,instanceof失效,可借Symbol.toStringTag补足类型识别。

JavaScript 中单例模式的核心是确保一个类只有一个实例,并提供全局访问点。闭包天然适合实现这一目标——它能封装私有变量和函数,避免污染全局作用域,同时通过返回的函数持续持有对内部状态的引用。
用闭包封装唯一实例
把实例缓存在闭包内部,对外只暴露一个获取实例的函数。每次调用该函数时,检查实例是否存在;不存在则新建,存在则直接返回。
- 闭包中的变量(如 instance)不会被外部直接访问,保证了“唯一性”的可控性
- 构造逻辑可放在内部函数中,支持懒加载(首次调用才初始化)
- 无需 class 或 new 关键字,纯函数式写法更轻量
基础实现示例
以下是一个典型写法:
const Singleton = (function() {
let instance = null;
function createInstance() {
return {
data: [],
add(item) { this.data.push(item); },
getData() { return this.data; }
};
}
return function() {
if (!instance) {
instance = createInstance();
}
return instance;
};
})();
// 使用
const a = Singleton();
const b = Singleton();
console.log(a === b); // true
支持参数化与初始化配置
如果单例需要初始化参数(如 API 地址、默认配置),可在首次调用时接收并缓存,后续调用忽略参数或抛出提示。
立即学习“Java免费学习笔记(深入)”;
- 把配置对象存在闭包内,作为实例的“初始化快照”
- 判断 instance 是否已存在,存在就跳过初始化逻辑
- 若需重置实例(极少数场景),可额外暴露一个 clear 方法,但应谨慎使用
注意原型链与 instanceof 的限制
闭包返回的对象是普通对象字面量,不是某个类的实例,因此 instanceof 会失效。
- 若需类型识别,可用 Symbol.toStringTag 或自定义 type 字段辅助判断
- 不依赖 instanceof 时,这种写法足够简洁可靠
- 想保留构造函数语义,可将类定义在闭包内,再控制 new 实例的次数


















