JavaScript 中的 Symbol

JavaScript 中的 Symbol

Symbol 是 ES6 引入的一种原始数据类型,表示独一无二的值。

基本特性

1. 唯一性

javascript 复制代码
const s1 = Symbol();
const s2 = Symbol();
console.log(s1 === s2); // false

// 即使描述相同,也不相等
const s3 = Symbol('id');
const s4 = Symbol('id');
console.log(s3 === s4); // false

2. 不能与 new 一起使用

javascript 复制代码
const s = Symbol(); // ✅ 正确
const s2 = new Symbol(); // ❌ TypeError: Symbol is not a constructor

创建 Symbol

javascript 复制代码
// 无描述
const sym = Symbol();

// 带描述(便于调试)
const symWithDesc = Symbol('mySymbol');
console.log(symWithDesc.toString()); // "Symbol(mySymbol)"
console.log(symWithDesc.description); // "mySymbol" (ES2019)

主要用途

1. 作为对象属性名(防止冲突)

javascript 复制代码
const id = Symbol('id');

const user = {
  name: '张三',
  [id]: 12345,  // 使用计算属性名
  age: 25
};

console.log(user[id]); // 12345
console.log(Object.keys(user)); // ['name', 'age'] - Symbol 属性不显示
console.log(Object.getOwnPropertySymbols(user)); // [Symbol(id)]

2. 定义常量(避免重复)

javascript 复制代码
// 传统方式(可能冲突)
const COLORS = {
  RED: 'RED',
  GREEN: 'GREEN',
  BLUE: 'BLUE'
};

// Symbol 方式(绝对唯一)
const COLORS_SYMBOL = {
  RED: Symbol('red'),
  GREEN: Symbol('green'),
  BLUE: Symbol('blue')
};

3. 模拟私有属性

javascript 复制代码
const _private = Symbol('private');

class MyClass {
  constructor(value) {
    this[_private] = value;
  }
  
  getValue() {
    return this[_private];
  }
}

const obj = new MyClass('secret');
console.log(obj.getValue()); // 'secret'
console.log(obj._private); // undefined - 无法直接访问

全局 Symbol 注册表

javascript 复制代码
// 创建/获取全局 Symbol
const globalSym1 = Symbol.for('global.id');
const globalSym2 = Symbol.for('global.id');
console.log(globalSym1 === globalSym2); // true

// 查看 key
console.log(Symbol.keyFor(globalSym1)); // 'global.id'

// 普通 Symbol 没有 key
const localSym = Symbol('local');
console.log(Symbol.keyFor(localSym)); // undefined

内置 Well-Known Symbols

用于自定义对象的行为:

javascript 复制代码
// Symbol.iterator - 使对象可迭代
const myIterable = {
  data: [1, 2, 3],
  [Symbol.iterator]: function() {
    let index = 0;
    return {
      next: () => {
        if (index < this.data.length) {
          return { value: this.data[index++], done: false };
        }
        return { done: true };
      }
    };
  }
};

for (const item of myIterable) {
  console.log(item); // 1, 2, 3
}

// 其他内置 Symbols
// Symbol.hasInstance - 自定义 instanceof
// Symbol.toPrimitive - 类型转换
// Symbol.toStringTag - 修改 toString 标签
// Symbol.species - 控制衍生对象类型
// Symbol.asyncIterator - 异步迭代器

重要注意事项

不会被遍历:

javascript 复制代码
const sym = Symbol('test');
const obj = {
  [sym]: 'secret',
  name: 'test'
};

// 以下方法不会包含 Symbol 属性
Object.keys(obj);      // ['name']
Object.values(obj);    // ['test']
JSON.stringify(obj);   // '{"name":"test"}'
Object.getOwnPropertyNames(obj); // ['name']

// 需要专门的方法
Object.getOwnPropertySymbols(obj); // [Symbol(test)]
Reflect.ownKeys(obj);  // ['name', Symbol(test)]

类型转换:

javascript 复制代码
const sym = Symbol('test');

// 可以转为字符串
String(sym);        // 'Symbol(test)'
sym.toString();     // 'Symbol(test)'

// 可以转为布尔值
Boolean(sym);       // true

// 不能转为数字或字符串拼接
Number(sym);        // ❌ TypeError
sym + '';           // ❌ TypeError
`sym: ${sym}`;      // ❌ TypeError

实际应用场景

  1. 防止属性名冲突(特别是库开发)
  2. 定义枚举常量(确保唯一性)
  3. 隐藏实现细节(虽然不是真正的私有)
  4. 自定义对象行为(迭代器、类型转换等)

Symbol 是 JavaScript 中一个非常有用的特性,特别适合需要唯一标识符的场景。

相关推荐
review44543几秒前
拿到 codex 第一步
前端·agent·vibecoding
鶴哥只手遮天11 分钟前
jQuery 4.0 源码架构与工程实践-第 01 章 · 全景与工程结构:一个 20 岁库的自省
前端·javascript·jquery
徐小夕28 分钟前
doc2docx方案,开源!
前端·vue.js·github
徐小夕33 分钟前
JitOFD:一款面向信创与档案场景的 Web 端 OFD 编辑器
前端·vue.js·github
孟健1 小时前
Kimi K3.1 Pro 编程实测:3个月27万行代码,每年1.7万预算下如何9分钟修好顽固Bug
前端·开源·ai编程
inksci1 小时前
在线编辑表格,功能强大,json互转
前端·javascript·html
咩咩啃树皮2 小时前
JavaScript 中 this 指向为什么总在变?
开发语言·前端·javascript
彭亚川Allen2 小时前
从零手搓 RAG 之 Embedding 技术
前端·后端·面试
OpenTiny社区2 小时前
GenUI SDK v1.4.0 的 React 渲染器到底做对了什么?
前端·github·ai编程
咩咩啃树皮2 小时前
JavaScript 异步流程为什么容易失控?从回调到可维护设计
开发语言·javascript·ecmascript