在 JavaScript 和 TypeScript 中,symbol
是一种原始数据类型(Primitive Type),用于创建唯一的标识符。它在 ES6 中被引入,主要用于解决属性名冲突问题,以及实现一些高级的编程模式。
symbol
的基本概念symbol
是一种原始数据类型,表示一个唯一的值。Symbol()
都会生成一个全新的、独一无二的值,即使它们的描述相同。const sym1 = Symbol("key");
const sym2 = Symbol("key");
console.log(sym1 === sym2); // false,因为每个 Symbol 都是唯一的
symbol
值也是不同的。symbol
是原始类型,不能被修改。symbol
不能直接与其他类型进行隐式转换(如与字符串拼接)。const sym = Symbol("test");
// console.log("Symbol: " + sym); // 报错:不能将 symbol 转换为字符串
console.log("Symbol: " + String(sym)); // 正确:显式转换为字符串
symbol
的用途symbol
可以用作对象的键,避免属性名冲突。这是 symbol
最常见的用途之一。
const id = Symbol("id");
const user = {
name: "Alice",
[id]: 123, // 使用 Symbol 作为键
};
console.log(user[id]); // 输出 123
console.log(user.name); // 输出 "Alice"
// Symbol 键不会出现在常规的枚举中
console.log(Object.keys(user)); // 输出 ["name"]
console.log(Object.getOwnPropertySymbols(user)); // 输出 [Symbol(id)]
通过 Symbol.for()
方法,可以创建一个全局共享的 symbol
。如果已经存在相同的描述字符串,则返回已存在的 symbol
。
const globalSym1 = Symbol.for("globalKey");
const globalSym2 = Symbol.for("globalKey");
console.log(globalSym1 === globalSym2); // true,因为它们来自全局注册表
console.log(Symbol.keyFor(globalSym1)); // 输出 "globalKey"
console.log(Symbol.keyFor(Symbol("localKey"))); // 输出 undefined,非全局 Symbol
JavaScript 提供了一些内置的 symbol
,用于实现特定的行为。这些内置 symbol
是语言的一部分,可以直接使用。
Symbol.iterator
:定义对象的迭代器方法。Symbol.toStringTag
:自定义对象的默认字符串标签。Symbol.toPrimitive
:定义对象的原始值转换行为。// 自定义迭代器
const iterable = {
[Symbol.iterator]() {
let step = 0;
return {
next() {
step++;
if (step <= 3) {
return { value: step, done: false };
}
return { done: true };
},
};
},
};
for (const value of iterable) {
console.log(value); // 输出 1, 2, 3
}
// 自定义 toStringTag
const obj = {
[Symbol.toStringTag]: "CustomObject",
};
console.log(Object.prototype.toString.call(obj)); // 输出 "[object CustomObject]"
symbol
在 TypeScript 中的使用TypeScript 对 symbol
提供了良好的支持,并将其视为一种独立的原始类型。
symbol
类型在 TypeScript 中,可以直接声明 symbol
类型的变量。
let sym: symbol = Symbol("test");
// const sym: unique symbol
const uniqueSym: unique symbol = Symbol("unique"); // 唯一符号类型
unique symbol
类型TypeScript 引入了 unique symbol
类型,用于表示一个完全唯一的 symbol
。这种类型只能通过 const
声明,并且不能赋值给其他变量。
const uniqueSym: unique symbol = Symbol("unique");
// let anotherSym: unique symbol = uniqueSym; // 报错:unique symbol 不能被重新赋值
symbol
作为对象的键TypeScript 支持使用 symbol
作为对象的键,并提供了类型检查。
const id = Symbol("id");
interface User {
name: string;
[id]: number; // 使用 Symbol 作为键
}
const user: User = {
name: "Alice",
[id]: 123,
};
console.log(user[id]); // 输出 123
TypeScript 为内置 symbol
提供了类型定义,开发者可以直接使用。
class IterableClass {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
}
}
const instance = new IterableClass();
for (const value of instance) {
console.log(value); // 输出 1, 2, 3
}
symbol
的优缺点symbol
键不会出现在常规的枚举中,适合实现私有属性。symbol
的值无法直接查看,可能增加调试复杂度。symbol
。symbol
的核心作用:
symbol
和 unique symbol
类型。symbol
作为对象的键,并提供类型检查。symbol
作为对象的私有属性键。symbol
扩展对象的行为。symbol
,以免增加代码的复杂性。