JavaScript中利用Symbol实现单例模式的属性锁定

Symbol 实现单例模式的核心是利用其唯一性和不可枚举性隔离实例引用,防止外部篡改或重复创建:通过 Symbol 键缓存实例(如静态属性或 WeakMap),并用 Object.defineProperty 锁定私有状态字段,但 Symbol 仅提供命名隔离,非绝对私有。用 Symbol 实现单例模式的属性锁定,核心是利用其唯一性和不可枚举性,防止外部篡改或重复创建实例。关键不在"锁住属性",而在于"隔离实例引用"------让构造函数只能返回同一个对象,且该对象的关键字段(如私有状态)不被外部覆盖或遍历。用 Symbol 作为私有实例缓存键将单例实例存在闭包或全局弱映射中,但用 Symbol 作键可避免被 for...in、Object.keys() 等枚举到,也不与字符串键冲突:在类外部声明一个 Symbol,用于存储唯一实例 构造函数检查该 Symbol 对应的值是否存在;若已存在,直接返回,不再新建 实例本身不暴露该 Symbol,外部无法通过点语法或方括号访问(除非拿到 Symbol 引用)示例:const INSTANCE = Symbol('singletonInstance');class Logger { constructor() { if (Logger[INSTANCE]) { return Logger[INSTANCE]; } Logger[INSTANCE] = this; this.logCount = 0; } log(msg) { console.log(`[{++this.logCount}\] {msg}`); }}配合 WeakMap 实现更安全的实例绑定直接挂载在类上(如 Logger[INSTANCE])虽简单,但存在被手动删除或覆盖的风险。用 WeakMap + Symbol 可进一步解耦:用 Symbol 作为 WeakMap 的键标识符(仅作逻辑区分,实际仍用 WeakMap 的 set/get) 把类本身作为 WeakMap 的键,实例作为值,确保每个类独享单例 WeakMap 的键必须是对象,且不阻止垃圾回收,比静态属性更健壮改进写法:const INSTANCE_KEY = Symbol('instanceKey');const instances = new WeakMap();class Database { constructor() { if (instances.has(this.constructor)) { return instances.get(this.constructor); } instances.set(this.constructor, this); this.connected = false; } connect() { this.connected = true; }}防止原型/实例属性被意外覆盖单例对象的内部状态(如 this._cache)容易被外部赋值覆盖。可用 Symbol 命名私有字段,并配合 Object.defineProperty 锁定: Mokker AI AI产品图添加背景

相关推荐
Devin~Y1 小时前
大厂Java面试实录:Spring Boot/WebFlux、JVM调优、Redis/Kafka、Spring Cloud 与 RAG/Agent 追问
java·jvm·spring boot·maven·mybatis·jpa·spring webflux
qq_296553271 小时前
矩阵逆时针旋转90度:三种解法从入门到精通
数据结构·python·算法·面试·矩阵
Elastic 中国社区官方博客1 小时前
在 Kubernetes 上的 Elastic Cloud:简化的可用区感知、重启和 mTLS
大数据·数据库·搜索引擎·云原生·容器·kubernetes·全文检索
声声codeGrandMaster1 小时前
seq2seq概念和数据集处理
人工智能·pytorch·python·算法·ai
努力努力再努力wz1 小时前
【Redis入门系列】Redis基础命令详解:从客户端连接到数据读写、key 管理与过期机制
c语言·开发语言·数据结构·数据库·c++·redis·缓存
m0_609160491 小时前
如何使用Python查询MongoDB并转为Pandas DataFrame_数据分析集成实战
jvm·数据库·python
环流_1 小时前
分清redis主要数据操作中的key
数据库·redis·哈希算法
西京刀客1 小时前
redis 大key使用 UNLINK 命令删除、Redis Set / ZSet 存储上限、ZRemRangeByRank命令
数据库·redis·缓存
woxihuan1234561 小时前
c++怎么利用std--variant处理多种二进制子协议包的自动分支解析【进阶】
jvm·数据库·python