下面给你一份 《前端(JavaScript)中单例模式的实现与应用实例》(2025 最新版),涵盖核心实现方式、ESModule 特性、实际应用场景和完整代码示例,非常适合用于项目、学习或写文章。
🚀 前端(JavaScript)中的单例模式实现与应用实例(2025 最全指南)
单例模式(Singleton):
保证一个类在全局只能有一个实例,并且可以全局访问。
JavaScript 中单例模式尤其常用,因为浏览器环境本身就是天然全局共享的。
⭐ 一、为什么 JS 中需要单例模式?
前端常见需要保证“全局只有一个实例”的场景:
| 场景 | 说明 |
|---|---|
| 全局状态管理 | 如用户信息、权限、配置 |
| 全局事件总线 EventBus | 避免多个实例导致事件丢失 |
| WebSocket 连接 | 整个应用只能有一个连接 |
| 弹窗组件(Dialog / Modal) | 避免多次渲染 |
| 缓存管理器 | 防止重复请求接口 |
| 配置中心 Config | 全局统一配置入口 |
⭐ 二、最常用的 5 种单例实现方式(含最佳实践)
① 基于闭包的单例(经典写法)
const Singleton = (function () {
let instance;
function createInstance() {
return { name: "singleton instance" };
}
return {
getInstance() {
if (!instance) instance = createInstance();
return instance;
}
};
})();
const a = Singleton.getInstance();
const b = Singleton.getInstance();
console.log(a === b); // true
优点:简单、独立,不依赖外部结构
缺点:无法与 ESModule 相结合
② 基于类 + 静态属性的单例模式(主流推荐)
class Store {
static instance = null;
constructor() {
if (Store.instance) return Store.instance;
this.data = {};
Store.instance = this;
}
}
const s1 = new Store();
const s2 = new Store();
console.log(s1 === s2); // true
优点:
- ES6 面向对象写法
- 实例天然可扩展
- 更适合大型项目
③ 使用 ESModule 的天然单例(最推荐)
ESModule 在浏览器 / Node 中天然只会加载一次。
⚡ 一个模块就是一个单例!
// store.js
export const store = {
user: null,
token: null
};
// app.js
import { store } from "./store.js";
store.user = { name: "阿杰" };
在其他组件中:
import { store } from "./store.js";
console.log(store.user); // 永远是同一个对象
优点:
✔ 最干净
✔ 无需额外代码保证单例
✔ 天然缓存(只执行一次)
✔ Vue / React 项目通用
现代前端优先推荐:使用 ESModule 实现单例!
④ 使用 Symbol + 全局注册表(解决多版本冲突)
用于避免多个 bundle 注入不同版本的实例,如微前端场景。
const KEY = Symbol.for("global.singleton");
if (!globalThis[KEY]) {
globalThis[KEY] = { count: 0 };
}
export default globalThis[KEY];
任何地方导入都获得同一个对象。
⑤ 立即执行函数 + WeakMap(私有化单例)
用于隐藏实现细节,不能被外部随意修改。
const Singleton = (function () {
const privateMap = new WeakMap();
return class {
constructor() {
if (!privateMap.has(Singleton)) {
privateMap.set(Singleton, this);
}
return privateMap.get(Singleton);
}
};
})();
const s1 = new Singleton();
const s2 = new Singleton();
console.log(s1 === s2); // true
⭐ 三、前端实际应用场景示例(超级实用)
1. WebSocket 单例(最常见)
class WS {
static instance = null;
constructor(url) {
if (WS.instance) return WS.instance;
this.ws = new WebSocket(url);
WS.instance = this;
}
}
export default new WS("wss://server.com");
避免多开 WebSocket 连接。
2. 全局事件总线(EventBus)单例
class EventBus {
static instance;
constructor() {
if (EventBus.instance) return EventBus.instance;
this.events = {};
EventBus.instance = this;
}
on(name, fn) {
(this.events[name] ||= []).push(fn);
}
emit(name, ...args) {
(this.events[name] || []).forEach(fn => fn(...args));
}
}
export default new EventBus();
3. 请求缓存器(防止重复请求)
class Cache {
static instance;
constructor() {
if (Cache.instance) return Cache.instance;
this.map = new Map();
Cache.instance = this;
}
async fetch(url) {
if (this.map.has(url)) return this.map.get(url);
const data = await fetch(url).then(r => r.json());
this.map.set(url, data);
return data;
}
}
export const cache = new Cache();
4. 全局配置中心 Config
export const config = {
api: "/api",
version: "1.0.0",
};
ESM 天然单例。
5. UI 弹窗(Modal)单例
避免重复渲染多个弹窗。
class ModalManager {
static instance;
constructor() {
if (ModalManager.instance) return ModalManager.instance;
this.visible = false;
ModalManager.instance = this;
}
show() { this.visible = true; }
hide() { this.visible = false; }
}
export default new ModalManager();
⭐ 四、最佳实践(2025 版本)
| 使用场景 | 推荐单例实现方式 |
|---|---|
| Vue/React 项目 | ESModule 单例(最干净) |
| 工具库 Class | 类静态属性单例 |
| 微前端、跨包共享 | Symbol.for + globalThis |
| 高性能动画、游戏场景 | IIFE + 对象池 |
| 私有化、安全性要求高 | WeakMap 私有化 |
⭐ 五、总结(可作为文章结尾)
JavaScript 实现单例模式有多种方式,但 2025 年最推荐:
优先使用 ESModule,因为加载一次、全局共享、最符合现代前端架构。
其他方式根据需求补充使用即可。