《设计模式?》前端单例模式保姆级教程:用 Class + 闭包各封装一个 LocalStorage 单例,一次学会!

哈喽掘友们,今天给你带来一个面试 + 实战双杀 的设计模式:
单例模式(Singleton Pattern)

别小看它,这玩意儿可是:

  • 设计模式里最基础、最实用的一个。
  • 你要是说不出来,面试官心里:嗯?没用过 Vuex?没写过封装工具?
  • 真正搞明白,工作里封装 storage、全局配置、状态管理都能用到。

别担心,今天咱直接手把手演示:

✅ 什么是单例?

✅ 为啥要单例?

✅ 怎么用 class 写单例?

✅ 怎么用 闭包 写单例?

✅ 两种写法有啥区别?

看完保证会用,还能跟面试官对吹不虚场!


什么是单例?

官方八股文:

单例模式是一种创建型设计模式 ,核心目的是:保证某个类在整个系统中只有一个实例,并提供全局访问点

人话:

一个类只能生一个娃,全局就这一个娃谁都得用它。


单例能干嘛?

常见场景:

  • 日志收集器(只有一个人负责记日志)
  • 配置中心(配置信息全局共享)
  • 状态管理(Vuex、Redux 本质上都是单例 store)
  • 工具封装(localStorage、sessionStorage 封装)
  • 连接池(后端里用得多,前端了解即可)

咱要干啥?

今天来动手封装一个**Storage 单例**,干嘛用?

  • 内部基于浏览器的 localStorage
  • 提供两个方法:setItem(key, value)getItem(key)
  • 自动序列化/反序列化,避免忘写 JSON.stringify

单例核心设计思路(class版)

咱先搞明白单例是怎么落地的,最常见就是:

1️⃣ 一个 static 静态属性 instance,负责 hold 住唯一实例。

2️⃣ 一个 static getInstance() 静态方法:

  • 如果没实例,就 new 一个挂上去;
  • 有了就直接 return。
    3️⃣ 使用时:Storage.getInstance() 永远拿到同一个对象。

✅ 上代码!Storage 单例 class

js 复制代码
class Storage {
  // 静态属性,hold 全局唯一实例
  static instance = null;

  // 静态方法,获取唯一实例
  static getInstance() {
    if (!Storage.instance) {
      Storage.instance = new Storage();
    }
    return Storage.instance;
  }

  // 设置
  setItem(key, value) {
    localStorage.setItem(key, JSON.stringify(value));
  }

  // 获取
  getItem(key) {
    const value = localStorage.getItem(key);
    try {
      return JSON.parse(value);
    } catch (e) {
      return value;
    }
  }
}

// 使用
const s1 = Storage.getInstance();
const s2 = Storage.getInstance();

s1.setItem('name', '掘金小白');
console.log(s2.getItem('name')); // 掘金小白

console.log(s1 === s2); // true,确实只有一个实例

✅ 分析一下

  • static:挂在类上,不在原型上,不属于实例。
  • getInstance():外部想要实例,都得走这里。
  • setItem/getItem:普通实例方法,挂在 prototype 上,实例共享。

这就是单例最经典的写法,大厂面试只要问到 "单例",脱口而出这套就没错


那闭包版是啥?为啥要有闭包版?

别急,闭包版也是面试爱问,原因是:

  • 早期没有 class,只能用函数 + 闭包模拟单例。
  • JS 的闭包很适合保存私有变量(就是把唯一实例藏起来)。
  • 有时候为了更灵活,也会用闭包来包装一些状态。

✅ 来,闭包版也走一个

思路:

  • 外层一个 IIFE(立即执行函数),内部声明唯一实例 let instance
  • 内部定义构造函数 StorageBase
  • StorageBase 构造里判断:有实例就直接 return,否则挂自己。
  • 返回这个构造函数。

js 复制代码
const Storage = (function() {
  let instance;

  function StorageBase() {
    if (instance) {
      return instance;
    }
    instance = this;
  }

  StorageBase.prototype.setItem = function(key, value) {
    localStorage.setItem(key, JSON.stringify(value));
  };

  StorageBase.prototype.getItem = function(key) {
    const value = localStorage.getItem(key);
    try {
      return JSON.parse(value);
    } catch (e) {
      return value;
    }
  };

  return StorageBase;
})();

// 使用
const s1 = new Storage();
const s2 = new Storage();

s1.setItem('job', '前端摸鱼王');
console.log(s2.getItem('job')); // 前端摸鱼王

console.log(s1 === s2); // true,闭包也 hold 住唯一实例

这俩写法有啥区别?

class 版 闭包版
核心依赖 ES6 class + static 函数 + 闭包
实现思路 静态属性存实例 闭包变量存实例
使用姿势 Storage.getInstance() new Storage()
场景 模块化/现代前端常用 老代码、灵活封装、函数式玩具

✅ 有啥坑要注意?

  • 闭包版一定别写错!不要 StorageBasenew StorageBase(),不然直接死递归爆栈(很多人翻车在这)。
  • 有些同学喜欢直接 export default new Storage(),这是模块化的懒汉式,天然单例,也没问题。
  • 闭包写法有点"老派",但考察你基础掌握得牢不牢。

总结一波

单例模式 = 一个类只能造一次,想用都找它要,不会多生孩子。

核心关键点

  • static + getInstance()(现代写法)
  • 闭包 hold 住唯一实例(经典写法)
  • 用在全局唯一、状态管理、工具封装

必背台词

单例是最简单的设计模式之一,核心就是保证全局唯一实例,提供可控访问点。实际场景可以是配置中心、缓存池、日志、全局状态管理等,既节省资源又利于统一管理。


面试杀招

面试官:会单例吗?

你:会啊,用 class 的话可以用 static 属性保存唯一实例,getInstance 做懒汉式;用闭包也可以 hold 实例,外面拿不到内部状态,保证只生成一次。

面试官:🫡,这小子还行!


写在最后

单例说简单真不难,但能写对,能讲清楚,能灵活切换实现方式,你就真的比很多人多拿一分 offer。

要是这篇帮你理清了单例,记得一键三连:

点个赞

收藏回头抄

留言:要不要我再写个「模块化 + TS 单例」的进阶版?

我是小阳,咱下次掘金再见,摸鱼人冲!

相关推荐
xkxnq2 分钟前
第二阶段:Vue 组件化开发(第 18天)
前端·javascript·vue.js
晓得迷路了3 分钟前
栗子前端技术周刊第 112 期 - Rspack 1.7、2025 JS 新星榜单、HTML 状态调查...
前端·javascript·html
怕浪猫6 分钟前
React从入门到出门 第五章 React Router 配置与原理初探
前端·javascript·react.js
jinmo_C++6 分钟前
从零开始学前端 · HTML 基础篇(一):认识 HTML 与页面结构
前端·html·状态模式
鹏多多12 分钟前
前端2025年终总结:借着AI做大做强再创辉煌
前端·javascript
哈__15 分钟前
React Native 鸿蒙跨平台开发:Vibration 实现鸿蒙端设备的震动反馈
javascript·react native·react.js
WebGISer_白茶乌龙桃18 分钟前
Cesium实现“悬浮岛”式,三维立体的行政区划
javascript·vue.js·3d·web3·html5·webgl
小Tomkk21 分钟前
⭐️ StarRocks Web 使用介绍与实战指南
前端·ffmpeg
不一样的少年_25 分钟前
产品催: 1 天优化 Vue 官网 SEO?我用这个插件半天搞定(不重构 Nuxt)
前端·javascript·vue.js
-dcr26 分钟前
50.智能体
前端·javascript·人工智能·ai·easyui