JavaScript中单例模式在对象创建中的实现与应用

1次阅读

单例模式确保类只有一个实例并提供全局访问点,在 JavaScript 中通过闭包、ES6 模块或静态属性实现。闭包方式用 IIFE 封装实例,模块方式利用导出唯一性,Class 方式借助 static 属性控制构造逻辑,适用于配置管理、日志器、状态仓库等场景。

JavaScript 中单例模式在对象创建中的实现与应用

单例模式确保一个类只有一个实例,并提供全局访问点。在 JavaScript 中,它不依赖 class 的私有机制或锁,而是靠闭包、模块作用域或静态属性控制实例的唯一性。

用闭包封装唯一实例

这是最经典、兼容性最好的实现方式。通过立即执行函数(IIFE)创建私有作用域,内部缓存实例,外部只能通过返回的函数获取该实例。

示例:

const Singleton = (function() {let instance = null;   return function() {if (!instance) {instance = {         data: [],         add(item) {this.data.push(item); },         getData() { return this.data;}       };     }     return instance;   }; })();  // 使用 const a = Singleton(); const b = Singleton(); console.log(a === b); // true

要点:instance 变量被闭包保护,无法从外部重置;每次调用 Singleton() 都返回同一个对象引用。

立即学习 Java 免费学习笔记(深入)”;

ES6 模块单例(推荐现代项目)

利用 ES6 模块的“单例加载”特性——模块脚本只执行一次,导出对象天然唯一。

示例(singleton.js):

// singleton.js export const instance = {config: { theme: 'light', lang: 'zh'},   updateConfig(newConf) {Object.assign(this.config, newConf);   } };

在任意文件中导入:

import {instance as appConfig} from './singleton.js'; import {instance as logger} from './singleton.js';  console.log(appConfig === logger); // true(同一模块,同一导出)

优势:无需手动判断、无闭包开销、天然支持 tree-shaking 和类型推导,适合配置管理、日志器、状态仓库等场景。

Class + 静态属性实现(兼顾面向对象风格)

适用于需要构造逻辑、继承或 TypeScript 类型约束的场景。用 static 属性保存实例,构造器限制重复创建。

class Database {constructor() {if (Database.instance) {return Database.instance;}     this.connection = `conn-${Date.now()}`;     Database.instance = this;   }    query(sql) {return `Executing: ${sql} on ${this.connection}`;   } }  // 使用 const db1 = new Database(); const db2 = new Database(); console.log(db1 === db2); // true

注意:这种方式在严格模式下 new 调用仍会新建 this,但最终返回的是已存在的 instance;若需彻底阻止重复初始化,可配合 Symbol 或 WeakMap 做更严谨校验。

典型应用场景

  • 全局配置中心 :如主题、用户偏好、API 基础路径,避免多处分散维护
  • 日志记录器 :统一格式、级别控制和输出目标,防止日志错乱或重复初始化
  • 状态管理实例 :如简易版 Store,多个组件共享同一状态快照
  • 第三方 SDK 封装 :如支付、地图、埋点 SDK,确保只初始化一次且 API 统一入口

不复杂但容易忽略:单例强调“唯一性”而非“全局变量”。应避免把普通对象挂到 window 上,而要通过可控的获取方式(函数调用 / 模块导入)来使用。

text=ZqhQzanResources