Skip to content

Symbols

symbols诞生的背景是自ECMAScript 2015起,symbol成为了一种新的原生类型,就像number和string一样。
在 JavaScript(以及 TypeScript,因为 TypeScript 是 JavaScript 的超集)中,Symbol 是一种原始数据类型,它代表独一无二的值。Symbol 用于创建对象的属性名,这些属性名是唯一的,不会被其他代码无意中覆盖或修改。

Symbols有哪些特征

使用Symbols要牢记这些特点,正式因为这些特点,是的Symbol有了存在的意义, Symbol 的主要特点包括: 唯一性:每个 Symbol 值都是唯一的。
不可枚举:Symbol 属性不会出现在对象的常规 for...in 循环中,也不会被 Object.keys() 或 Object.getOwnPropertyNames() 方法枚举。 不可改变:Symbol 属性的值是不可改变的,不能被修改。 描述字符串:创建 Symbol 时可以提供一个描述字符串,用于在调试时识别 Symbol。

创建

symbol类型的值是通过Symbol构造函数创建的。

ts
let sym1 = Symbol();
let sym2 = Symbol("key"); // 可选的字符串key

Symbol一点创建就是不可变的,而且是唯一的

ts
let sym2 = Symbol("key");
let sym3 = Symbol("key");

sym2 === sym3; // false, symbols是唯一的

在 TypeScript 中,Symbol 的用途与 JavaScript 中相同,但由于 TypeScript 提供了类型系统和编译时检查,因此在使用 Symbol 时可以获得更多的类型安全保证。以下是 Symbol 在 TypeScript 中的一些常见用途:

  1. 作为对象属性的键:使用 Symbol 作为对象属性的键可以确保属性名不会与对象的其他属性发生冲突。
typescript
const firstName = Symbol('firstName');
const person = {
  [firstName]: 'John'
};
console.log(person[firstName]); // John
  1. 定义元数据属性Symbol 可以用于定义一些不应该被直接访问的元数据属性,例如,用于调试或内部逻辑的属性。
typescript
const debugMode = Symbol('debugMode');
class MyClass {
  [debugMode]: boolean;
  constructor(debug: boolean) {
    this[debugMode] = debug;
  }
  log(message: string) {
    if (this[debugMode]) {
      console.log(message);
    }
  }
}
const instance = new MyClass(true);
instance.log('Debugging is enabled');
  1. 扩展内置对象:使用 Symbol 可以安全地扩展内置对象,如 ArrayObject 等,而不会覆盖已有的方法或属性。
typescript
const myMethod = Symbol('myMethod');
Array.prototype[myMethod] = function() {
  // 扩展数组原型的方法
};
const array = [1, 2, 3];
array[myMethod](); // 调用扩展的方法
  1. 迭代器和生成器:在实现自定义迭代器或生成器时,可以使用 Symbol.iteratorSymbol.asyncIterator 作为对象的键。
typescript
const iterable = {
  [Symbol.iterator]: function* () {
    yield 1;
    yield 2;
    yield 3;
  }
};
for (const value of iterable) {
  console.log(value);
}
  1. 元编程:在元编程中,Symbol 可以用于定义一些特殊的元属性,例如 Symbol.toStringTag,它用于自定义对象的 Object.prototype.toString.call() 方法的返回值。
typescript
const myObject = {
  [Symbol.toStringTag]: 'MyObject'
};
console.log(Object.prototype.toString.call(myObject)); // [object MyObject]
  1. 类型安全的 Symbol:在 TypeScript 中,可以使用 unique symbol 类型来创建类型安全的 Symbol,确保每个 unique symbol 都是独一无二的。
typescript
const mySymbol = Symbol() as unique symbol;
// 使用类型断言创建一个 unique symbol
const anotherSymbol = Symbol() as unique symbol;
// mySymbol 和 anotherSymbol 是不同类型的 unique symbol

使用 Symbol 在 TypeScript 中可以提供更安全、更可靠的代码,尤其是在处理大型项目和多人协作时。通过避免命名冲突和提高代码的可读性,Symbol 成为了一个非常有用的特性。

Symbol的成员和使用实例

TypeScript 中的 Symbol 是 JavaScript Symbol 的类型版本,它们在 TypeScript 中没有特殊的“默认成员”的概念。然而,JavaScript 有一系列内置的 Symbol 值,这些值在 TypeScript 中也被广泛使用。这些内置的 Symbol 值通常用于元编程,即编写影响程序本身行为的代码。以下是 JavaScript(和 TypeScript)中一些重要的内置 Symbol 值及其作用:

  1. Symbol.iterator
    • 作用:定义对象的默认迭代器。当对象被用于 for...of 循环时,会调用这个方法。
typescript
const iterable = {
  [Symbol.iterator]: function* () {
    yield 1;
    yield 2;
    yield 3;
  }
};
for (const value of iterable) {
  console.log(value); // 1, 2, 3
}
  1. Symbol.asyncIterator
    • 作用:定义对象的异步迭代器。用于 for await...of 循环,允许异步迭代对象。
typescript
const asyncIterable = {
  [Symbol.asyncIterator]: async function* () {
    yield 1;
    yield 2;
    yield 3;
  }
};
for await (const value of asyncIterable) {
  console.log(value); // 1, 2, 3
}
  1. Symbol.toStringTag
    • 作用:用于自定义对象的 Object.prototype.toString.call() 方法的返回值。
typescript
const myObject = {
  [Symbol.toStringTag]: 'MyObject'
};
console.log(Object.prototype.toString.call(myObject)); // [object MyObject]
  1. Symbol.hasInstance
    • 作用:用于确定一个对象是否是某个构造函数的实例。这是 instanceof 操作符的钩子。
typescript
class MyClass {
  static [Symbol.hasInstance](instance) {
    return false;
  }
}
const obj = new MyClass();
console.log(obj instanceof MyClass); // false
  1. Symbol.isConcatSpreadable
    • 作用:一个布尔值,指示对象是否应该被 Array.prototype.concat 方法展开其数组元素。
typescript
const arrayLike = {
  length: 2,
  0: 'a',
  1: 'b',
  [Symbol.isConcatSpreadable]: true
};
console.log(['x', 'y'].concat(arrayLike)); // ['x', 'y', 'a', 'b']
  1. Symbol.unscopables
    • 作用:一个对象,其属性指示哪些属性不应该被 with 语句包含。
typescript
Array.prototype[Symbol.unscopables] = {
  copyWithin: true,
  entries: true,
  fill: true,
  find: true,
  findIndex: true,
  // ... 更多属性
};
with (Array.prototype) {
  copyWithin; // undefined
}
  1. Symbol.match
    • 作用:用于定义一个正则表达式的匹配行为。
typescript
const regex = /hello/;
regex[Symbol.match] = function() {
  return ['world'];
};
console.log('hello world'.match(regex)); // ['world']
  1. Symbol.replace
    • 作用:用于定义一个正则表达式的替换行为。
typescript
const regex = /hello/;
regex[Symbol.replace] = function() {
  return 'world';
};
console.log('hello world'.replace(regex)); // 'world world'
  1. Symbol.search
    • 作用:用于定义一个正则表达式的搜索行为。
typescript
const regex = /hello/;
regex[Symbol.search] = function() {
  return 6;
};
console.log('hello world'.search(regex)); // 6
  1. Symbol.split
    • 作用:用于定义一个正则表达式的分割行为。
typescript
const regex = /hello/;
regex[Symbol.split] = function() {
  return ['world'];
};
console.log('hello world'.split(regex)); // ['world']

这些内置的 Symbol 值在 TypeScript 中同样适用,并且 TypeScript 会提供对这些特殊方法的类型检查。这些 Symbol 值的使用使得开发者可以更精细地控制对象的行为,特别是在涉及到迭代、正则表达式和元编程的场景中。

仅用于培训和测试,通过使用本站代码内容随之而来的风险与本站无关。版权所有,未经授权请勿转载,保留一切权利。
ICP备案号:滇ICP备15009214号-13   公安网备:滇公网安备 53312302000061号