JavaScriptSymbol类型怎样创建唯一值【教程】

3次阅读

symbol值天然唯一,Symbol(‘a’)与Symbol(‘a’)不相等;Symbol.for(‘key’)可跨上下文共享同一Symbol;Symbol用作对象键时不可被常规遍历方法访问。

JavaScriptSymbol类型怎样创建唯一值【教程】

Symbol 类型创建的值天然唯一,哪怕描述相同,Symbol('a')Symbol('a') 也不相等 —— 这是它最核心的特性,不是“模拟唯一”,而是语言层保证。

Symbol() 创建基础唯一值

每次调用 Symbol()(无论带不带参数)都返回一个全新、不可复现的值:

const a = Symbol('id'); const b = Symbol('id'); console.log(a === b); // false console.log(typeof a); // "symbol"

参数(如 'id')仅作描述,不影响唯一性,也不参与比较。调试时能在控制台看到这个描述,但代码里不能靠它识别 Symbol。

  • 不传参:Symbol() 也是合法的,描述为 undefined
  • 参数建议用字符串,其他类型会强制转字符串(Symbol(42) 等价于 Symbol('42')
  • 不能用 new Symbol(),会报 TypeError: Symbol is not a constructor

Symbol.for() 创建全局登记的 Symbol

当需要跨模块、跨执行上下文“共享同一个 Symbol”时,用 Symbol.for(key)。它会先在全局 Symbol 注册表中查找,存在就返回,否则新建并登记:

const s1 = Symbol.for('debug'); const s2 = Symbol.for('debug'); console.log(s1 === s2); // true

注意:Symbol.for('x')Symbol('x') 完全不同,前者可被复用,后者永远唯一。

  • 键名(key)必须是字符串,否则抛错
  • 注册表是全局的,所有代码共享,命名要谨慎避免冲突
  • 可用 Symbol.keyFor(sym) 反查某个 Symbol 是否登记过、登记的键是什么

Symbol 作为对象属性键的注意事项

Symbol 最常用场景是定义“不会被遍历到、不易被意外覆盖”的属性:

  • Object.keys()for...injsON.stringify() 都忽略 Symbol 键
  • 要用 Object.getOwnPropertySymbols()Reflect.ownKeys() 才能拿到
  • 赋值写法: obj[mySym] = 'hidden',不能用点号 obj.mySym
  • 若想让 Symbol 属性可枚举,需显式设置 enumerable: true(默认 false

常见陷阱:用 Symbol.iterator 实现自定义迭代器时,必须确保它是全局内置 Symbol,而不是自己 Symbol('iterator') —— 否则 for...of 不认。

哪些 Symbol 是内置的?怎么用?

es6+ 预定义了一批以 Symbol. 开头的全局 Symbol,用于定制对象行为,比如:

  • Symbol.iterator:让对象支持 for...of
  • Symbol.toStringTag:影响 Object.prototype.toString.call(obj) 的输出
  • Symbol.hasInstance:影响 instanceof 判断逻辑
  • Symbol.toPrimitive:控制对象转原始值(如 +obj、`${obj}`)

这些都不能重写或覆盖,只能在对象上定义对应方法来响应。例如实现 Symbol.iterator,必须把它作为属性键挂到对象上,且值是一个返回迭代器的函数。

真正容易被忽略的是:Symbol 本身不能被 json 序列化,也不能直接 console.log 输出完整结构(只显示描述),调试时如果依赖打印看 Symbol 属性,得手动提取或用 Object.getOwnPropertySymbols() 辅助检查。

text=ZqhQzanResources