以下是11 个内置 Symbol 及其典型使用场景或面试题。
1. Symbol.iterator
用途 :定义对象的默认迭代器,用于 for...of、扩展运算符 ... 等。
ts
const myIterable = {
[Symbol.iterator]() {
let step = 0;
return {
next() {
step++;
if (step <= 3) return { value: step, done: false };
return { done: true };
}
};
}
};
for (const v of myIterable) {
console.log(v); // 1, 2, 3
}
面试题
如何让
{ a: 1, b: 2, c: 3 }这样的普通对象支持for...of循环?
ts
const obj = {
a: 1,
b: 2,
c: 3,
*[Symbol.iterator]() {
yield* Object.values(this)[Symbol.iterator]();
},
};
for (const val of obj) {
console.log(val); // 输出: 1, 2, 3
}
如何实现一个无限递增数字的迭代器?
ts
const infiniteCounter = {
*[Symbol.iterator]() {
let count = 0;
while (true) {
yield count++;
}
},
};
const iterator = infiniteCounter[Symbol.iterator]();
console.log(iterator.next().value); // 0
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
// ...无限递增
2. Symbol.asyncIterator(ES2018)
用途 :异步数据流(如分页API),用于 for await...of。
ts
const asyncPager = {
data: [1, 2, 3, 4, 5],
pageSize: 2,
currentPage: 0,
async *[Symbol.asyncIterator]() {
while (this.currentPage * this.pageSize < this.data.length) {
const start = this.currentPage * this.pageSize;
const end = start + this.pageSize;
const chunk = this.data.slice(start, end);
yield new Promise((resolve) => {
setTimeout(() => resolve(chunk), 1000); // 模拟异步请求
});
this.currentPage++;
}
}
};
(async () => {
for await (const page of asyncPager) {
console.log(page); // [1, 2] (1秒后) → [3, 4] (1秒后) → [5] (1秒后)
}
})();
3. Symbol.toStringTag
用途 :自定义 Object.prototype.toString.call(obj) 的输出。
ts
class MyComponent {
get [Symbol.toStringTag]() {
return 'MyVueComponent';
}
}
console.log(Object.prototype.toString.call(new MyComponent()));
// "[object MyVueComponent]"
应用场景:调试、日志、类型识别(如 Vue/React 组件标识)。
4. Symbol.hasInstance
用途 :自定义 instanceof 的行为。
ts
class MyArray {
static [Symbol.hasInstance](instance) {
return Array.isArray(instance);
}
}
console.log([1, 2] instanceof MyArray); // true
面试题
实现一个 NegativeNumber类,使得任何负数都是它的实例。
ts
class NegativeNumber {
static [Symbol.hasInstance](instance) {
return typeof instance === 'number' && instance < 0;
}
}
console.log(-5 instanceof NegativeNumber); // true
console.log(5 instanceof NegativeNumber); // false
5. Symbol.isConcatSpreadable
用途 :控制数组 concat 时是否展开。
ts
const arr1 = [1, 2];
const arr2 = [3, 4];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr1.concat(arr2)); // [1, 2, [3, 4]]
6. Symbol.species
用途 :指定派生类构造函数(如 map、filter 返回的实例类型)。
ts
class MyArray extends Array {
static get [Symbol.species]() {
return Array; // map/filter 返回普通 Array 而非 MyArray
}
}
const a = new MyArray(1, 2, 3);
console.log(a.map(x => x * 2) instanceof MyArray); // false
常见于:自定义集合类(如 Immutable.js、RxJS)。
7. Symbol.match
用途 :定义 String.prototype.match 调用时的行为。
ts
const matcher = {
[Symbol.match](str) {
return str.includes('hello') ? ['hello'] : null;
}
};
console.log('say hello'.match(matcher)); // ['hello']
8. Symbol.replace
用途 :定义 String.prototype.replace 的行为。
ts
const replacer = {
[Symbol.replace](str, substr) {
return str.split(' ').join(substr);
}
};
console.log('a b c'.replace(replacer, '-')); // "a-b-c"
9. Symbol.search
用途 :定义 String.prototype.search 的行为。
ts
const searcher = {
[Symbol.search](str) {
return str.indexOf('world');
}
};
console.log('hello world'.search(searcher)); // 6
10. Symbol.split
用途 :定义 String.prototype.split 的行为。
ts
const splitter = {
[Symbol.split](str) {
return str.split(/[\s,]+/);
}
};
console.log('a b,c'.split(splitter)); // ['a', 'b', 'c']
11. Symbol.unscopables
用途 :指定在 with 语句中被排除的属性(现代 JS 中极少使用)。
ts
Array.prototype[Symbol.unscopables] = { copyWithin: true };
with ([]) {
// copyWithin 不会被引入作用域
}
注意 :由于
with已被严格模式禁用,此 Symbol 几乎无实际用途。