简介
symbol 是 ECMAScript 2015(也称为 ES6)引入的一个新的原始数据类型。它主要用于创建对象的唯一属性名。在 TypeScript 中,你可以使用 symbol 类型来确保对象属性的唯一性,以及其他与符号相关的操作。
与其他原始类型(如 number 或 string)不同,symbol 是不可变的且唯一的。
创建 symbol 类型的值:
let sym1 = Symbol();
let sym2 = Symbol("key"); // 可选的字符串key
unique symbol
在 TypeScript 中,有一种特殊的 symbol 类型,称为 unique symbol。这种类型的符号是通过 Symbol() 或 Symbol.for() 构造器创建的,并且使用 const 声明。使用 unique symbol 类型可以确保一个符号永远不会与其他任何符号值相等。
const symUnique: unique symbol = Symbol();
这意味着,如果你试图将其他任何 symbol 值赋给 symUnique,TypeScript 将会抛出一个类型错误。
类型推断
在 TypeScript 中,当你使用 Symbol() 构造函数创建一个新的符号时,TypeScript 将自动为其推断 symbol 类型。
let sym = Symbol();
// TypeScript understands 'sym' is of type 'symbol'
但是,当使用 const 关键字与 unique symbol 类型声明一个符号时,TypeScript 将为其推断一个特定的唯一符号类型。
const uniqueSym: unique symbol = Symbol();
// TypeScript understands 'uniqueSym' is of a unique symbol type
这种类型推断使得符号的使用在 TypeScript 中更加类型安全,因为它可以确保你不会意外地用其他符号值替换一个 unique symbol。
unique symbol 和 symbol 的区别
symbol 和 unique symbol 都是 TypeScript 中的数据类型,它们都代表唯一的、不可变的数据值,但它们之间有一些关键的区别:
-
创建方式:
symbol: 可以通过Symbol()或Symbol.for()创建。unique symbol: 只能通过Symbol()创建,并且必须使用const声明。
-
唯一性:
symbol: 虽然通过Symbol()创建的每个符号都是唯一的,但symbol类型的变量可以被任何symbol值赋值。unique symbol: 一旦为unique symbol类型的变量赋值,该变量不能被其他任何symbol值重新赋值。这确保了其绝对的唯一性。
-
类型安全性:
symbol: 提供了一定的类型安全性,因为符号是唯一的。unique symbol: 提供了更强的类型安全性,因为尝试将其他symbol值赋给unique symbol类型的变量会导致 TypeScript 抛出类型错误。
-
使用场景:
symbol: 通常用于创建对象的唯一属性键,以避免属性名冲突。unique symbol: 当你需要确保某个符号值绝对不会与其他任何符号值相等时,例如在创建单例模式或特定的唯一标识符时。
总之,unique symbol 是 symbol 的一个更加严格的子类型,它提供了更强的唯一性和类型安全性。
Symbol() 和 Symbol.for()
Symbol() 和 Symbol.for() 都是用于创建符号的方法,但它们的工作方式和用途略有不同。以下是如何使用这两种方法创建符号的详细说明:
1. 使用 Symbol()
Symbol() 创建一个新的、唯一的符号值。你可以为它提供一个可选的描述字符串,但这个描述只是为了调试目的,不能用于访问符号。
示例:
const sym1 = Symbol();
const sym2 = Symbol('description');
console.log(sym1); // Symbol()
console.log(sym2); // Symbol(description)
注意:即使两个符号有相同的描述,它们也是不相等的。
const sym3 = Symbol('test');
const sym4 = Symbol('test');
console.log(sym3 === sym4); // false
2. 使用 Symbol.for()
Symbol.for() 会首先检查是否存在一个与给定键关联的符号在全局符号注册表中。如果存在,它会返回该符号;否则,它会创建一个新的符号并将其与该键关联。
示例:
const sym5 = Symbol.for('example');
const sym6 = Symbol.for('example');
console.log(sym5); // Symbol(example)
console.log(sym6); // Symbol(example)
console.log(sym5 === sym6); // true
在上面的示例中,sym5 和 sym6 都是使用相同的键 "example" 通过 Symbol.for() 创建的。因为它们都引用全局符号注册表中的同一个符号,所以它们是相等的。
总结:
- 使用
Symbol()创建的每个符号都是唯一的。 - 使用
Symbol.for()创建的符号可能不是唯一的,因为它会首先尝试从全局符号注册表中检索符号。
选择哪种方法取决于你的具体需求。如果你需要一个确保唯一的符号,使用 Symbol()。如果你需要跨多个执行上下文共享符号,使用 Symbol.for()。
总结
symbol 类型在 JavaScript 和 TypeScript 中为开发者提供了创建不可变、唯一键值的能力,这对于避免命名冲突和与私有属性相关的其他用途特别有用。而 TypeScript 的类型系统进一步增强了与 symbol 相关的类型安全性,特别是引入了 unique symbol 这一概念。