Well-known Symbols
Symbol is a built-in object and considered as a primitive type like numbers, booleans, etc.
Everytime we call the Symbol()
function, we get a value which is guaranteed to be unique.
let v1 = Symbol();
let v2 = Symbol();
console.log(v1 === v2); // false
There is a special type of symbols call well-known symbols, which is used to customize object behaviors.
Before symbols, if we want customize how to convert object to string, we can define the toString
method. Same logic, if we want to customize how to convert object to JSON, we can define the toJSON
method. This approach is not ideal, because these method is no different to normal methods. If we want to add more control, we add a new method toXXX
, then this method may be the same with your normal methods, then comes the problem.
Now with symbol, because it is guranteed to be unique, so it is suitable for this kind of usage. Now let explore some of them to see how to use them.
Symbol.toStringTag
Customize how to convert object to string.
const obj1 = {
x: 100,
y: 200,
}
console.log(String(obj1)) // [object Object]
const obj2 = {
x: 100,
y: 200,
toString() {
return this.x + "-" + this.y
}
}
console.log(String(obj2)) // 100-200
const obj3 = {
x: 100,
y: 200,
get [Symbol.toStringTag]() {
return this.x + "-" + this.y
}
}
console.log(String(obj3)) // [object 100-200]
Symbol.iterator
Make the object iterable.
let range = {
from: 1,
to: 10,
[Symbol.iterator]() {
let current = this.from
, last = this.to;
return {
next() {
return (current <= last)
? { done: false, value: current++ }
: { done: true };
}
};
}
};
for (let num of range) {
console.log(num); // 1, 2, 3, 4, 5, ...
}
Symbol.toPrimitive
Customize how to convert object to primitive values.
let obj = {
value: 100,
[Symbol.toPrimitive](hint) {
if (hint === 'number') return +this.value;
if (hint === 'string') return "value: " + this.value.toString();
return this.value.toString();
}
};
console.log(+obj); // 100
console.log(`${obj}`); // value: 100
Note that there is a hint parameter which is used to know what should the target primitive type is.
Symbol.split
Customize split function.
let obj = {
[Symbol.split](value) {
return value.split("_").filter(v => /\d/.test(v))
}
}
console.log("1_2_3_a_5".split(obj))
// [ '1', '2', '3', '5' ]
Same logic goes with Symbol.match
, Symbol.replace
, Symbol.search
.