In the chapter “What You Don’t Know about Types”, you learned that javascript has a built-in Symbol. ToPrimitive property that allows you to customize type conversion operations.
typeof
We use Typeof most often for type detection, and using Typeof for basic types gives us the results we want
console.log(typeof '123') //'string'
console.log(typeof 123) //'number'
console.log(typeof undefined) //'undefined'
console.log(typeof true) //'boolean'
console.log(typeof Symbol('foo')) //'symbol'
Copy the code
Using Typeof for complex types is not what we want.
console.log(typeof {a: 1}) //'object'
console.log(typeof new Date()) //'object'
console.log(typeof [1.3.4]) //'object'
console.log(typeof new String('123')) //'object'
console.log(typeof new RegExp()) //'object'
Copy the code
Obviously, when we type new Date(), we want to get Date; When typing an Array, you want to get an Array, but when typeof is used, the result is always Object, so when typeof is used for complex types, the result is always Object.
There are two special values, and typeof checking for them is different from what you might expect
console.log(typeof null) //'object'
console.log(typeof function fn(){}) //'function'
Copy the code
Even though null is a primitive type, typeof results in object when used for type detection. Whereas function is a complex type, typeof detection is function.
Be careful to use Typeof for type detection when you are unsure of your type.
toString
The toString method is used instead of typeof to determine exactly what type you want
let type = {}.toString
console.log(type.call('123')) //'[object String]'
console.log(type.call(123)) //'[object Number]'
console.log(type.call(true)) //'[object Boolean]'
console.log(type.call(undefined)) //'[object Undefined]'
console.log(type.call(Symbol('foo'))) //'[object Symbol]'
console.log(type.call(null)) //'[object Null]'
console.log(type.call(function fn() {})) //'[object Function]'
console.log(type.call({a: 11})) //'[object Object]'
console.log(type.call(new Date)) //'[object Date]'
console.log(type.call(new RegExp)) //'[object RegExp]'
console.log(type.call([1.2.3])) //'[object Array]'
Copy the code
ToString is a good way to solve the problem of type determination. From the above example, we can see that both basic and complex types can be accurately determined.
Here {}. ToString (). Call (123), equivalent to the Object. The prototype. ToString. Call (123).
Symbol.toPrimitive
We’ve seen how to do type checking. When you do type checking, you’re actually doing a conversion. So how does conversion work inside javascript?
Javascript provides toSring and valueOf conversion methods when converting an object to a primitive type.
let o = {
valueOf: (a)= > {console.log('valueOf'); },
toString: (a)= > {console.log('toString');}
}
String(o) //'toString'
Number(o) //'valueOf'
Copy the code
When an object is converted toString, the toString method is called; The valueOf method is called when an object is converted to a number.
If a toString call does not get a base type value, valueOf is called, and a valueOf call does not get a base type, and TypeError is reported
The same is true when valueOf is called.
So why is the toString method called first when converting toString and the valueOf method when converting to number?
This is because javascript has a symbol.toprimitive property built in. When an object is to be converted to a primitive type, symbol.toprimitive is called and a hint argument is passed:
- If I want to convert to
string
.hint
A value ofstring
Is called sequentiallytoString
,valueOf
.toString
Must be executed if the basic type is returnedreturn
, terminates the operation, otherwise the call continuesvalueOf
, if calledvalueOf
If the base type is not available, it is reportedTypeError
Error; - If I want to convert to
number
.hint
A value ofnumber
Is called sequentiallyvalueOf
,toString
.valueOf
Must be executed if the basic type is returnedreturn
, terminates the operation, otherwise the call continuestoString
Method if calledtoString
If the base type is not available, it is reportedTypeError
Error; - If you are not sure whether to convert to
string
ornumber
.hint
A value ofdefault
Is called sequentiallyvalueOf
,toString
.valueOf
Must be executed if the basic type is returnedreturn
, terminates the operation, otherwise the call continuestoString
Method if calledtoString
If the base type is not available, it is reportedTypeError
Error.
How to display the user specified Symbol. ToPrimitive method, which calls the user defined Symbol. ToPrimitive method directly:
let o = {
[Symbol.toPrimitive](hint){
console.log(`hint: ${hint}`)},valueOf: (a)= > {console.log('valueOf'); }, / / not executed
toString: (a)= > {console.log('toString'); }/ / not executed
}
String(o) //'hint: string'
Number(o) //'hint: number'
o + ' ' //'hint: default'
Copy the code