Built-in Symbol values
ECMAScript 6 introduced the Symbol
type as a new primitive data type, along with a series of standard Symbol
values to extend object behavior. These built-in Symbol
values are exposed as properties of the Symbol
function, such as Symbol.iterator
and Symbol.toStringTag
, which define default iteration behavior or string descriptions for objects, among other features.
Symbol.iterator
Symbol.iterator
defines the default iterator for an object. If an object implements the Symbol.iterator
method, it is iterable and can be traversed using a for...of
loop.
const myIterable = {
[Symbol.iterator]: function* () {
yield 1;
yield 2;
yield 3;
}
};
for (const value of myIterable) {
console.log(value); // Outputs 1, 2, 3 in sequence
}
Built-in types like arrays, strings, Map, and Set already implement the Symbol.iterator
method by default:
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
is used to customize the string tag returned when Object.prototype.toString()
is called on an object. By default, a plain object returns [object Object]
, but defining Symbol.toStringTag
can change this behavior.
class MyClass {
get [Symbol.toStringTag]() {
return 'MyClass';
}
}
const obj = new MyClass();
console.log(Object.prototype.toString.call(obj)); // [object MyClass]
Built-in types like Map
and Set
also use this feature:
console.log(Object.prototype.toString.call(new Map())); // [object Map]
console.log(Object.prototype.toString.call(new Set())); // [object Set]
Symbol.species
Symbol.species
specifies the constructor for derived objects. When creating derived objects (e.g., new arrays returned by map
or filter
methods), the constructor specified by Symbol.species
is used.
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
customizes the behavior of the instanceof
operator. By default, instanceof
checks the object's prototype chain, but defining Symbol.hasInstance
can override this logic.
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
controls whether an array or array-like object is spread when the concat
method is called. By default, arrays are spread, while array-like objects are not.
const arr1 = [1, 2];
const arr2 = [3, 4];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr1.concat(arr2)); // [1, 2, [3, 4]]
For array-like objects, setting Symbol.isConcatSpreadable
to true
allows them to be spread:
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
defines how an object is converted to a primitive value. When an object needs to be converted to a string, number, or default primitive value, this method is called.
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
defines how an object behaves when passed to String.prototype.match
. If an object implements Symbol.match
, it can be used as an argument for 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
defines how an object behaves when passed to String.prototype.replace
. For example, custom replacement logic can be implemented:
class MyReplacer {
[Symbol.replace](string, replacement) {
return string.split(' ').join(replacement);
}
}
console.log('hello world'.replace(new MyReplacer(), '-')); // "hello-world"
Symbol.search
Symbol.search
defines how an object behaves when passed to String.prototype.search
. Custom search logic can be implemented:
class MySearcher {
[Symbol.search](string) {
return string.indexOf('world');
}
}
console.log('hello world'.search(new MySearcher())); // 6
Symbol.split
Symbol.split
defines how an object behaves when passed to String.prototype.split
. Custom splitting logic can be implemented:
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
specifies which properties of an object should not be bound by a with
statement. This is a legacy feature, as modern code rarely uses with
statements.
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作为对象属性