ZetCode

TypeScript Symbol 类型

最后修改于 2025 年 2 月 25 日

TypeScript 中的 Symbol 类型是一种原始数据类型,表示一个唯一且不可变的值。Symbol 通常用作对象属性的唯一标识符,确保它们不会与其他属性发生冲突。本教程涵盖了 TypeScript 中 Symbol 类型的创建、使用和实际示例。

Symbol 是唯一且不可变的值,可用作对象属性的标识符。它们使用 Symbol() 函数创建,并且每个 Symbol 都保证是唯一的,即使它们的描述相同。Symbol 通常用于创建对象中的私有或不可枚举属性。

创建 Symbol

此示例演示了如何在 TypeScript 中创建和使用 Symbol。

creating_symbols.ts
const symbol1 = Symbol();
const symbol2 = Symbol("description");

console.log(symbol1);  // Output: Symbol()
console.log(symbol2);  // Output: Symbol(description)

Symbol() 函数创建一个新的唯一 Symbol。可以提供一个可选的描述作为参数,这对于调试很有用,但不会影响 Symbol 的唯一性。

将 Symbol 用作对象属性

此示例演示了如何将 Symbol 用作对象属性的唯一键。

symbol_properties.ts
const idSymbol = Symbol("id");

let user = {
    name: "Alice",
    [idSymbol]: 12345
};

console.log(user[idSymbol]);  // Output: 12345

Symbol 可用作对象属性的键。这确保了属性不会与其他属性冲突,即使它们的名称相同。Symbol 键使用方括号访问。

Symbol 和迭代

此示例演示了在对象迭代期间如何处理 Symbol。

symbol_iteration.ts
const idSymbol = Symbol("id");

let user = {
    name: "Alice",
    age: 30,
    [idSymbol]: 12345
};

for (let key in user) {
    console.log(key);  // Output: name, age
}

console.log(Object.keys(user));  // Output: ["name", "age"]

Symbol 属性不包含在标准的で对象迭代方法(如 for...inObject.keys())中。这使得 Symbol 对于创建私有或隐藏属性非常有用。

全局 Symbol 注册表

此示例演示了如何使用全局 Symbol 注册表创建和共享 Symbol。

global_symbols.ts
const globalSymbol1 = Symbol.for("globalId");
const globalSymbol2 = Symbol.for("globalId");

console.log(globalSymbol1 === globalSymbol2);  // Output: true

Symbol.for() 方法从全局 Symbol 注册表中创建或检索 Symbol。使用相同键创建的 Symbol 是相同的,这使得它们可用于在代码的不同部分共享。

知名 Symbol

此示例演示了如何使用知名 Symbol 来自定义对象行为。

well_known_symbols.ts
let obj = {
    [Symbol.toStringTag]: "CustomObject"
};

console.log(obj.toString());  // Output: [object CustomObject]

知名 Symbol 是预定义的 Symbol,它们允许我们自定义对象的行为。例如,Symbol.toStringTag 可用于自定义 toString() 方法的输出。

唯一 Symbol

唯一 Symbol 是保证在您的代码库中唯一的 Symbol。唯一 Symbol 类型可确保您创建的每个 Symbol 都具有唯一的身份,即使它们的描述相同。当您想在对象上创建不会与其他任何属性键冲突的属性时,它们特别有用。

unique_symbols.ts
const uniqueSymbol1: unique symbol = Symbol("unique1");
const uniqueSymbol2: unique symbol = Symbol("unique2");

let obj = {
    [uniqueSymbol1]: "Value for uniqueSymbol1",
    [uniqueSymbol2]: "Value for uniqueSymbol2"
};

console.log(obj[uniqueSymbol1]);
console.log(obj[uniqueSymbol2]);

提供的代码演示了唯一 Symbol 的用法。

知名 Symbol

知名 Symbol 是内置 Symbol,代表对象的内部行为或属性。它们由 ECMAScript 规范预定义,可用于更改或自定义对象在某些操作中的行为方式。这些 Symbol 包括 Symbol.iteratorSymbol.asyncIteratorSymbol.matchSymbol.replace 等。

Symbol.iterator

Symbol.iterator 是一个知名 Symbol,用于定义对象的默认迭代器。具有 Symbol.iterator 属性的对象被认为是可迭代的,这意味着它可以在 for...of 循环、扩展运算符和其他与迭代相关的操作中使用。与 Symbol.iterator 关联的值是一个返回迭代器对象的函数。此迭代器对象必须符合迭代协议,该协议包括一个 next() 方法,该方法返回一个具有 value 和 done 属性的对象。

it_sym.ts
const Grades = {
    values: ['A', 'B', 'C', 'D', 'E', 'F', 'FX'],
    [Symbol.iterator]: function* () {
        for (let value of this.values) {
            yield value;
        }
    }
};

for (let value of Grades) {
    console.log(value); 
}

该代码定义了一个名为 Grades 的对象,其中包含一个名为 values 的数组,该数组包含年级字母。它还使用 Symbol.iterator Symbol 定义了一个自定义迭代器,这是一个生成器函数,它会产生 values 数组中的每个年级。这使得 Grades 对象可迭代。当在 Grades 上使用 for...of 循环时,将调用自定义迭代器,并且每个年级会按顺序记录到控制台。

Symbol.match

Symbol.match 是一个知名 Symbol,它允许自定义 String.prototype.match 方法的行为。通过在对象上实现 Symbol.match 方法,您可以控制如何将该对象用于匹配字符串。

match_sym.ts
class CustomMatcher {
    [Symbol.match](str: string) {
        return str.includes("TypeScript");
    }
}

const result = "I love TypeScript!".match(new CustomMatcher());
console.log(result); // Output: true

提供的代码定义了一个名为 CustomMatcher 的类,其中包含 Symbol.match 方法的自定义实现,该方法检查给定的字符串是否包含子字符串“TypeScript”。然后,该类的实例与字符串“I love TypeScript!” 的 match 方法一起使用,调用自定义的 Symbol.match 方法。

Symbol.split

Symbol.split 是一个知名 Symbol,它允许开发人员自定义 String.prototype.split 方法的行为。通过在对象上实现 Symbol.split 方法,您可以定义当该对象用作 split 方法的参数时,它将如何拆分字符串。本质上,它允许您根据自定义标准控制拆分字符串的逻辑。

这个知名 Symbol 提供了一种扩展或覆盖拆分字符串的默认行为的方法,让您在代码中执行字符串操作时拥有更大的灵活性。当在带有具有 Symbol.split 方法的对象的字符串上调用 split 方法时,JavaScript 将使用此自定义方法来确定字符串应如何拆分为子字符串数组。

split_sym.ts
class CustomSplitter {
    [Symbol.split](str: string) {
        return str.split(new RegExp(/[,;]+/));
    }
}

const result = "1,2,3;4,5,6;7;8".split(new CustomSplitter());
console.log(result); // Output: [ "1", "2", "3", "4", "5", "6", "7", "8" ]

提供的 TypeScript 代码定义了一个名为 CustomSplitter 的类,其中包含 Symbol.split 方法的自定义实现,该方法通过逗号或分号拆分给定的字符串。然后,该类的实例与提供的字符串的 split 方法一起使用,调用自定义的 Symbol.split 方法。

使用 Symbol 的最佳实践

来源

TypeScript Symbol 文档

在本文中,我们探讨了 TypeScript Symbol 类型,并通过实际示例演示了其用法。

作者

我的名字是 Jan Bodnar,我是一名热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直撰写编程文章。到目前为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 TypeScript 教程