Skip to main content

Symbol

在 JavaScript/TypeScript 中,有几个特殊的 Symbol 会在对象被特定操作时自动调用。以下是一些常用的 Symbol 及其触发时机:

1. Symbol.toPrimitive

当对象需要被转换为原始值(如字符串、数字等)时调用:

const obj = {
[Symbol.toPrimitive](hint: "default" | "string" | "number") {
if (hint === "number") return 42;
if (hint === "string") return "hello";
return "default";
},
};

console.log(Number(obj)); // 42
console.log(String(obj)); // 'hello'
console.log(obj + ""); // 'default'

2. Symbol.iterator

定义对象的默认迭代器,用于 for...of 循环和解构等场景:

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

for (const value of myIterable) {
console.log(value); // 1, 2, 3
}

3. Symbol.asyncIterator

定义对象的异步迭代器,用于 for await...of 循环:

const asyncIterable = {
[Symbol.asyncIterator]: async function* () {
yield "hello";
yield "world";
},
};

(async () => {
for await (const x of asyncIterable) {
console.log(x); // 'hello', 'world'
}
})();

4. Symbol.toStringTag

自定义对象的 Object.prototype.toString() 返回值:

const obj = {
[Symbol.toStringTag]: "MyCustomObject",
};

console.log(Object.prototype.toString.call(obj)); // '[object MyCustomObject]'

5. Symbol.hasInstance

自定义 instanceof 操作符的行为:

class MyArray {
static [Symbol.hasInstance](instance: any) {
return Array.isArray(instance);
}
}

console.log([] instanceof MyArray); // true

6. Symbol.species

用于创建派生对象时指定构造函数:

class MyArray extends Array {
static get [Symbol.species]() {
return Array;
}
}

const a = new MyArray(1, 2, 3);
const mapped = a.map((x) => x * 2);

console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array); // true

7. Symbol.match, Symbol.replace, Symbol.search, Symbol.split

自定义字符串匹配和替换行为:

const customMatcher = {
[Symbol.match](str: string) {
return str.includes("hello") ? ["hello"] : null;
},
};

console.log("hello world".match(customMatcher)); // ['hello']

8. Symbol.isConcatSpreadable

控制数组或类数组对象在 concat() 方法中的展开行为:

const arr1 = [1, 2];
const arr2 = [3, 4];
arr2[Symbol.isConcatSpreadable] = false;
console.log([].concat(arr1, arr2)); // [1, 2, [3, 4]]

9. Symbol.unscopables

用于 with 语句中,排除某些属性:

const obj = {
foo: 1,
bar: 2,
[Symbol.unscopables]: {
foo: true,
},
};

with (obj) {
console.log(bar); // 2
console.log(foo); // ReferenceError: foo is not defined
}

这些 Symbol 提供了对 JavaScript 对象行为的底层控制能力,可以用于实现更高级的抽象和元编程功能。