Symbol 是 JavaScript 中唯一、不可变的原始类型,用于创建防冲突的私有属性键或对接语言机制(如 Symbol.iterator);它不参与隐式转换,不可枚举,不被 JSON 序列化,需用方括号访问。
它不是字符串,也不能被隐式转换成字符串(除非显式调用 toString()),更不会参与对象属性名的自动类型转换。一个 Symbol() 调用总会返回一个新值,哪怕描述相同:Symbol('a') !== Symbol('a')。这点决定了它天然适合做“防冲突”的键。
当多个模块/库向同一个对象注入方法或元数据时,普通字符串键容易撞车。用 Symbol 可以确保隔离:
const isReady = Symbol('isReady');
const cach
eKey = Symbol('cacheKey');
const obj = {
[isReady]: false,
[cacheKey]: null
};
// 外部代码遍历 Object.keys(obj) 或 for...in 都看不到这两个属性
// 只有通过 Object.getOwnPropertySymbols(obj) 才能拿到
JSON.stringify() 序列化Object.assign() 拷贝(除非手动提取 getOwnPropertySymbols)obj.isReady 是 undefined,必须用方括号:obj[isReady]
如果需要多个地方引用同一个 Symbol(比如统一的事件类型标识),要用 Symbol.for(key):
const eventCancel = Symbol.for('event.cancel');
const sameRef = Symbol.for('event.cancel');
console.log(eventCancel === sameRef); // true
Symbol.for() 查找全局注册表,不存在则创建并登记;Symbol() 每次都新建Symbol.keyFor(eventCancel) 返回 'event.cancel'
Symbol.iterator)让对象支持语言级语法JavaScript 引擎在遇到 for...of、展开运算符、Array.from() 等时,会自动查找对象上的 [Symbol.iterator] 方法。你可以自己实现迭代逻辑:
const countdown = {
from: 3,
[Symbol.iterator]() {
return {
current: this.from,
next() {
if (this.current > 0) {
return { value: this.current--, done: false };
}
return { done: true };
}
};
}
};
[...countdown]; // [3, 2, 1]
Symbol.toStringTag(影响 Object.prototype.toString.call(x) 输出)、Symbol.hasInstance(自定义 instanceof 行为)、Symbol.toPrimitive(控制对象转原始值)TypeError: x is not iterable)for...of)。其余场景,字符串键更直白、更易调试。