内置Symbol值
ECMAScript 6 引入了Symbol
类型作为新的原始数据类型,同时还内置了一系列标准Symbol
值,用于扩展对象的行为。这些内置Symbol
值通过Symbol
函数的属性暴露,例如Symbol.iterator
和Symbol.toStringTag
,它们定义了对象的默认迭代行为或字符串描述等特性。
Symbol.iterator
Symbol.iterator
定义了对象的默认迭代器。如果一个对象实现了Symbol.iterator
方法,那么它就是可迭代的,可以被for...of
循环遍历。
const myIterable = {
[Symbol.iterator]: function* () {
yield 1;
yield 2;
yield 3;
}
};
for (const value of myIterable) {
console.log(value); // 依次输出 1, 2, 3
}
数组、字符串、Map、Set等内置类型都默认实现了Symbol.iterator
方法:
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
Symbol.toStringTag
Symbol.toStringTag
用于定制对象在调用Object.prototype.toString()
时返回的字符串标签。默认情况下,普通对象调用toString()
会返回[object Object]
,但通过定义Symbol.toStringTag
可以改变这一行为。
class MyClass {
get [Symbol.toStringTag]() {
return 'MyClass';
}
}
const obj = new MyClass();
console.log(Object.prototype.toString.call(obj)); // [object MyClass]
内置类型如Map
和Set
也使用了这一特性:
console.log(Object.prototype.toString.call(new Map())); // [object Map]
console.log(Object.prototype.toString.call(new Set())); // [object Set]
Symbol.species
Symbol.species
用于指定派生对象的构造函数。当需要创建派生对象(如数组的map
、filter
方法返回的新数组)时,会使用Symbol.species
指定的构造函数。
class MyArray extends Array {
static get [Symbol.species]() {
return Array;
}
}
const myArray = new MyArray(1, 2, 3);
const mappedArray = myArray.map(x => x * 2);
console.log(mappedArray instanceof MyArray); // false
console.log(mappedArray instanceof Array); // true
Symbol.hasInstance
Symbol.hasInstance
用于自定义instanceof
操作符的行为。默认情况下,instanceof
会检查对象的原型链,但通过定义Symbol.hasInstance
可以覆盖这一逻辑。
class MyClass {
static [Symbol.hasInstance](instance) {
return typeof instance === 'number';
}
}
console.log(1 instanceof MyClass); // true
console.log('1' instanceof MyClass); // false
Symbol.isConcatSpreadable
Symbol.isConcatSpreadable
用于控制数组或类数组对象在调用concat
方法时是否展开。默认情况下,数组会展开,而类数组对象不会。
const arr1 = [1, 2];
const arr2 = [3, 4];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr1.concat(arr2)); // [1, 2, [3, 4]]
对于类数组对象,可以通过设置Symbol.isConcatSpreadable
为true
来使其展开:
const arrayLike = {
0: 'a',
1: 'b',
length: 2,
[Symbol.isConcatSpreadable]: true
};
console.log(['x', 'y'].concat(arrayLike)); // ['x', 'y', 'a', 'b']
Symbol.toPrimitive
Symbol.toPrimitive
用于定义对象转换为原始值时的行为。当对象需要转换为字符串、数字或默认原始值时,会调用该方法。
const obj = {
[Symbol.toPrimitive](hint) {
if (hint === 'number') {
return 42;
}
if (hint === 'string') {
return 'forty-two';
}
return 'default';
}
};
console.log(+obj); // 42
console.log(`${obj}`); // "forty-two"
console.log(obj + ''); // "default"
Symbol.match
Symbol.match
用于定义对象在被String.prototype.match
调用时的行为。如果对象实现了Symbol.match
方法,那么它可以被用作match
的参数。
class MyMatcher {
[Symbol.match](string) {
return string.indexOf('hello') !== -1;
}
}
console.log('hello world'.match(new MyMatcher())); // true
console.log('hi world'.match(new MyMatcher())); // false
Symbol.replace
Symbol.replace
用于定义对象在被String.prototype.replace
调用时的行为。例如,可以自定义替换逻辑:
class MyReplacer {
[Symbol.replace](string, replacement) {
return string.split(' ').join(replacement);
}
}
console.log('hello world'.replace(new MyReplacer(), '-')); // "hello-world"
Symbol.search
Symbol.search
用于定义对象在被String.prototype.search
调用时的行为。可以自定义搜索逻辑:
class MySearcher {
[Symbol.search](string) {
return string.indexOf('world');
}
}
console.log('hello world'.search(new MySearcher())); // 6
Symbol.split
Symbol.split
用于定义对象在被String.prototype.split
调用时的行为。可以自定义分割逻辑:
class MySplitter {
[Symbol.split](string) {
return string.split(' ').map(word => word.toUpperCase());
}
}
console.log('hello world'.split(new MySplitter())); // ["HELLO", "WORLD"]
Symbol.unscopables
Symbol.unscopables
用于指定对象的哪些属性不应该被with
语句绑定。这是一个历史遗留特性,现代代码中很少使用with
语句。
const obj = {
a: 1,
b: 2,
[Symbol.unscopables]: {
a: true
}
};
with (obj) {
console.log(b); // 2
console.log(a); // ReferenceError: a is not defined
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益,请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:全局Symbol注册表
下一篇:Symbol作为对象属性