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 中一个非常有用的特性,特别适合需要唯一标识符的场景。

相关推荐
老王以为1 小时前
Claude Code 从 GUI 到 TUI:开发者界面的范式回归
前端·人工智能·全栈
JYeontu1 小时前
正方体翻滚Loading 2.0
前端·javascript·css
llq_3501 小时前
React 组件处理 Props
前端
夫子3961 小时前
多人协同后内容丢失?一文搞懂ONLYOFFICE document.key的正确用法
前端
张元清1 小时前
React 与用户偏好:尊重用户已经在 OS 里设过的那些选项
前端·javascript·面试
RPGMZ1 小时前
RPGMZ 游戏场景全局提示框 带三秒隐藏插件
前端·javascript·游戏·rpgmz
宠..1 小时前
VS Code 修改 C++ 标准同时修改错误检测标准
java·linux·开发语言·javascript·c++·python·qt
JarvanMo1 小时前
2026年最佳Flutter图标包
前端
Arthur14726122865471 小时前
Vue Query 缓存机制实战:别再让 gcTime 和 staleTime 背锅了
前端