前端JavaScript中Symbol的11个内置符号的使用场景详解
作者:th739
这篇文章主要为大家详细介绍了前端JavaScript中Symbol的11个内置符号及其典型使用场景或面试题,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
1.Symbol.iterator
用途:定义对象的默认迭代器,用于 for...of、扩展运算符 ... 等。
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循环?
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
}
如何实现一个无限递增数字的迭代器?
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。
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) 的输出。
class MyComponent {
get [Symbol.toStringTag]() {
return 'MyVueComponent';
}
}
console.log(Object.prototype.toString.call(new MyComponent()));
// "[object MyVueComponent]"
应用场景:调试、日志、类型识别(如 Vue/React 组件标识)。
4.Symbol.hasInstance
用途:自定义 instanceof 的行为。
class MyArray {
static [Symbol.hasInstance](instance) {
return Array.isArray(instance);
}
}
console.log([1, 2] instanceof MyArray); // true
面试题
实现一个 NegativeNumber类,使得任何负数都是它的实例。
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 时是否展开。
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 返回的实例类型)。
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 调用时的行为。
const matcher = {
[Symbol.match](str) {
return str.includes('hello') ? ['hello'] : null;
}
};
console.log('say hello'.match(matcher)); // ['hello']
8.Symbol.replace
用途:定义 String.prototype.replace 的行为。
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 的行为。
const searcher = {
[Symbol.search](str) {
return str.indexOf('world');
}
};
console.log('hello world'.search(searcher)); // 6
10.Symbol.split
用途:定义 String.prototype.split 的行为。
const splitter = {
[Symbol.split](str) {
return str.split(/[\s,]+/);
}
};
console.log('a b,c'.split(splitter)); // ['a', 'b', 'c']
11.Symbol.unscopables
用途:指定在 with 语句中被排除的属性(现代 JS 中极少使用)。
Array.prototype[Symbol.unscopables] = { copyWithin: true };
with ([]) {
// copyWithin 不会被引入作用域
}
注意:由于 with 已被严格模式禁用,此 Symbol 几乎无实际用途。
到此这篇关于前端JavaScript中Symbol的11个内置符号的使用场景详解的文章就介绍到这了,更多相关JavaScript Symbol内置符号内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
