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

相关推荐
漂流瓶jz11 分钟前
Webpack如何实现万物皆可import?loader的使用/配置/手写实践
前端·javascript·webpack
ZC跨境爬虫27 分钟前
跟着 MDN 学CSS day_41:显式轨道、隐式网格与区域命名放置
前端·javascript·css·ui·交互
修己xj1 小时前
告别手动存图!这款叫 Fatkun 的浏览器插件,简直是素材收集神器
前端
袋鼠云数栈2 小时前
从前端到基础设施,ACOS 如何打通企业全链路可观测
运维·前端·人工智能·数据治理·数据智能
AskHarries2 小时前
系统提示词、开发者指令和用户输入的优先级
java·前端·数据库
Moment2 小时前
长上下文会最终杀死 Rag 吗?
前端·javascript·后端
qcx233 小时前
【系统学AI】25 论文导读 ①:两篇改变 AI 的开山之作——Attention Is All You Need & ReAct
前端·人工智能·react.js·transformer
kyriewen4 小时前
大文件上传最全指南:分片、断点续传、秒传,一篇就够了
前端·javascript·面试
我叫黑大帅4 小时前
解决聊天页内部滚轮改为页面滚动问题
javascript·后端·面试
郑洁文5 小时前
基于Python的Web命令执行漏洞自动化检测系统
前端·python·网络安全·自动化