Skip to content

详细讲一下 Symbol 数据类型特征与实际使用案例?

Posted on:2024年8月14日 at 12:26

Symbol 是 ES6 引入的一种基本数据类型,它用于创建唯一且不可变的值。它主要用于解决对象属性的命名冲突问题。以下是 Symbol 的主要特征和实际使用案例:

1. 特征

1.1 唯一性

每个 Symbol 值都是唯一的,即使它们具有相同的描述。两个不同的 Symbol 对象即使描述相同,也不会相等。

const sym1 = Symbol("description");
const sym2 = Symbol("description");

console.log(sym1 === sym2); // false

1.2 不可变性

Symbol 的值是不可变的,一旦创建,就不能改变。

1.3 隐私性

Symbol 属性不容易与其他属性冲突,因为每个 Symbol 都是唯一的。它们不会被 for...in 循环、Object.keys()JSON.stringify() 处理,但可以通过 Object.getOwnPropertySymbols() 获取。

2. 创建 Symbol

使用 Symbol() 函数创建 Symbol:

const sym = Symbol("description");
console.log(sym); // Symbol(description)

3. 实际使用案例

3.1 用作对象属性的唯一标识符

Symbol 可以用作对象的属性键,避免属性名冲突。

const mySymbol = Symbol("uniqueProperty");

const obj = {
  [mySymbol]: "value",
};

console.log(obj[mySymbol]); // 'value'

3.2 定义私有对象属性

使用 Symbol 可以定义对象的“私有”属性,这些属性不会被意外覆盖或枚举到。

const privateProp = Symbol("private");

class MyClass {
  constructor(value) {
    this[privateProp] = value;
  }

  getPrivate() {
    return this[privateProp];
  }
}

const instance = new MyClass("secret");
console.log(instance.getPrivate()); // 'secret'
console.log(instance[privateProp]); // 'secret' (if you have the Symbol reference)

3.3 定义和使用内置对象的符号属性

JavaScript 内置对象(如 Object, Array, String 等)有一些 Symbol 属性,用于定义特定行为或协议。

const iterable = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  },
};

for (const value of iterable) {
  console.log(value); // 1, 2, 3
}
const obj = {
  [Symbol.toStringTag]: "MyObject",
};

console.log(Object.prototype.toString.call(obj)); // [object MyObject]
class MyClass {
  static [Symbol.hasInstance](instance) {
    return instance instanceof Array;
  }
}

console.log([] instanceof MyClass); // true
console.log({} instanceof MyClass); // false
const obj = {
  [Symbol.toPrimitive](hint) {
    if (hint === "string") return "string representation";
    if (hint === "number") return 42;
    return "default representation";
  },
};

console.log(String(obj)); // 'string representation'
console.log(Number(obj)); // 42
console.log(obj + 1); // 43

4. 组合使用

4.1 扩展对象的行为

Symbol 还可以与其他 ES6 特性组合使用,例如 Proxy 和 Reflect API 来扩展对象行为。

示例代码

const handler = {
  get(target, prop, receiver) {
    if (prop === Symbol.toStringTag) {
      return "CustomObject";
    }
    return Reflect.get(target, prop, receiver);
  },
};

const proxy = new Proxy({}, handler);
console.log(Object.prototype.toString.call(proxy)); // [object CustomObject]
原文转自:https://fe.ecool.fun/topic/675f2f01-6304-49e6-aacc-71d754fcb7d4