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

相关推荐
福兮说11 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理12 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆66612 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
凤城老人13 小时前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron
Dovis(誓平步青云)13 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan13 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_14 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒14 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
广州华水科技14 小时前
大坝安全监测解决方案:单北斗GNSS形变监测系统应用与维护
前端
yivifu15 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub