Wang Li, the author of this article, is a senior front-end engineer of New Oriental Online, mainly responsible for the design and development of user transaction, user growth and other related systems.
Before the body begins, look at this code:
[] = =! []// ?
{} == ! {} // ?
Copy the code
What is this? Meng…
I think it’s a cast.
Come on, don’t be confused, read the following article, you will understand.
Cast casting
Number()
Parameter is primitive type
// Value: the original value after conversion
Number(123) / / 123
// String: If it can be parsed to a numeric value, it is converted to the corresponding numeric value
Number('123') / / 123
// String: If it cannot be parsed as a number, return NaN
Number('123abc') // NaN
// The empty string is converted to 0
Number(' ') / / 0
// Boolean values: true to 1, false to 0
Number(true) / / 1
Number(false) / / 0
// undefined: becomes NaN
Number(undefined) // NaN
// null: converts to 0
Number(null) / / 0
Copy the code
Number() converts a string to a Number, stricter than the parseInt function. Basically, if a single character cannot be converted to a numeric value, the entire string is converted to NaN. However, parseInt can handle string interception and numeric notation:
parseInt('32 abc') / / 32
parseInt('0x11 abc') / / 17
Number('32 abc') // NaN
Number('0x11 abc') // NaN
Copy the code
Parameter is object
When Number() takes an object, it is almost always converted to NaN, except for an array containing a single value.
Number({ a : 1 }) // NaN
Number([ 1.2.3 ]) // NaN
Number([ 5 ]) / / 5
Copy the code
Why is that? What the hell happened?
Let’s start with this code:
const obj = {
toString: function() {
return 1;
},
valueOf: function() {
return 2; }};console.log(Number(obj)); / / 2
Copy the code
Number(obj) Invokes the valueOf method. The output is 2. Make some changes to the code above:
const obj = {
toString: function() {
return 1;
},
valueOf: function() {
return{}; }};console.log(Number(obj)); / / 1
Copy the code
The result is 1, and Number(obj) calls the toString method. Now look at the following code:
const obj = {
toString: function() {
return {};
},
valueOf: function() {
return{}; }};console.log(Number(obj)); / / an error
Copy the code
Uncaught TypeError: Cannot convert object to primitive value What if I delete the toString method?
const obj = {
valueOf: function(){
return{}; }};console.log(Number(obj)); // NaN
Copy the code
In the above code, Number({}) calls the default toString method, the toString method on Object.prototype. The specific process is shown in the following code:
/ / dismantling Number ({})
Object.prototype.toString.call({}) // "[object Object]"
Number("[object Object]") // NaN
Copy the code
In the example above, valueOf returns an object. Let’s look at how it returns an array.
const obj = {
valueOf: function(){
return[]; }};console.log(Number(obj)) / / 0
Copy the code
In the above code Number(obj) is equivalent to Number([]), which calls Array’s toString method instead of Object’s toString. As follows:
/ / dismantling Number ([])
Array.prototype.toString.call([]) / / ""
Number(' ') / / 0
Copy the code
Then look at the Object. The prototype. ToString:
Object.prototype.toString.call([]) //'[object Array]'
Number('[object Array]') // NaN
Copy the code
When Number() takes an object type, the following conclusions can be drawn:
-
Calls the valueOf method of the object itself. If a value of the original type is returned, the Number function is used directly on the value without further steps.
-
If the valueOf method still returns an object, the toString method of the object itself is called instead. If the toString method returns a value of the original type, the Number function is used on the value without further steps.
-
If toString returns an object, an error is reported.
Object. The prototype. ToString return values:
// Primitive type
Object.prototype.toString.call('123') // '[object String]'
Object.prototype.toString.call(123) // '[object Number]'
Object.prototype.toString.call(NaN) // '[object Number]'
Object.prototype.toString.call(Infinity) // '[object Number]'
Object.prototype.toString.call(null) // '[object Null]'
Object.prototype.toString.call(undefined) // '[object Undefined]'
// Reference type
Object.prototype.toString.call(function() {}) // '[object Function]'
Object.prototype.toString.call([1.2.3]) // '[object Array]'
Object.prototype.toString.call([1]) // '[object Array]'
Object.prototype.toString.call({}) // '[object Object]'
Object.prototype.toString.call(new Error()) // '[object Error]'
Object.prototype.toString.call(/\d/) // '[object RegExp]'
Object.prototype.toString.call(Date()) // '[object String]'
Object.prototype.toString.call(new Date()) // '[object Date]'
Object.prototype.toString.call(Symbol()) // '[object Symbol]'
// Provided by the browser
(function (){
Object.prototype.toString.call(arguments) // '[object Symbol]'}) ()Object.prototype.toString.call(document) // '[object HTMLDocument]'
Object.prototype.toString.call(window) // '[object Window]'
Copy the code
String()
Parameter is primitive type
When String() takes a primitive data type:
- Value: Converts to the corresponding string
- String: the original value after conversion
- Boolean values: true to string ‘true’, false to string ‘false’
- Undefined: converts to string ‘undefined’
- Null: Converts to string ‘null’
A code example is as follows:
String(123) / / "123"
String('abc') // "abc"
String(true) // "true"
String(undefined) // "undefined"
String(null) // "null"
Copy the code
Parameter is object
When String() takes an object type:
String({ a: 1 }) // "[object Object]"
String([1.2.3]) / / "1, 2, 3"
Copy the code
const obj = {
toString: function() {
return 1;
},
valueOf: function() {
return 2; }};console.log(String(obj)) / / 1
Copy the code
String() has the same conversion rules as Number(), except that valueOf and toString methods are executed in the same order.
-
We call the toString method of the object itself. If a value of the original type is returned, the String function is used for that value and the following steps are not performed.
-
If the toString method returns an object, call the valueOf method of the original object. If the valueOf method returns a valueOf the original type, the String function is used for that value and the following steps are not performed.
-
If valueOf returns an object, an error is reported.
Different types of toString methods have different results:
[1.2].toString() === Array.prototype.toString.call([1.2]) // true
Array.prototype.toString.call([1.2= =])Object.prototype.toString.call([1.2]) // false
Copy the code
Boolean()
Falsey (imaginary)
When a Boolean type is converted, an imaginary value is converted to false. There are several types of imaginary values:
undefined
null
0 / / + 0-0
NaN
false
' '
Copy the code
Other situations
All but imaginary values are true:
Boolean([]) // true
Boolean({}) // true
Boolean(new Error()) // true
Boolean(Symbol()) // true
Copy the code
Implicit type conversion/automatic conversion
Automatically converts to a Boolean value
These symbols are automatically converted to Boolean values:
if(a)for while switch! !!!!! = = =? : && | |Copy the code
Implicit type conversion: All but imaginary values are converted to true
Automatically converts to a string
Automatic conversion of strings occurs mainly during string addition operations. When one value is a string and the other is a non-string, the latter is converted to a string.
'5' + 1 / / '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
'5' + [] / / "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
null+ []?null+ {}?null + funciton() {}
Copy the code
Automatically converts to a value
Except for the addition operator (+), which may convert operands to strings, all arithmetic operators automatically convert operands to numbers.
'5' - '2' / / 3
'5' * '2' / / 10
true - 1 / / 0
false - 1 // -1
'1' - 1 / / 0
'5' * [] / / 0
false / '5' / / 0
'abc' - 1 // NaN
null + 1 / / 1
undefined + 1 // NaN
Copy the code
Note: null is 0 when converted to a value, and undefined is NaN when converted to a value.
In positive/negative sign operators:
+'abc' // NaN
-'abc' // NaN
+true / / 1
-false / / 0
Copy the code
Relational operators such as ==! ==, will also be converted to a number.
1= =true // true
'1'= =true // true
'1'= =1 // true
[1] = =1 // true
[1] = =true // true[] = =false // true[] = =null // false
[1.2] = =NaN // false
Copy the code
Special values
Infinity
Number(Infinity) //Infinity
1 / 0= =Infinity // true
1 / Infinity= =0 // true
Infinity= = =Infinity // true
Infinity= = = -Infinity // false
0= = = -0 // true
0 / 0 // NaN
Copy the code
NaN
NaN= =NaN // false
Copy the code
Undefined and null
null= = =null // true
undefined= = =undefined // true
undefined= =null // true
undefined= = =null // false
Copy the code
conclusion
Now let’s answer the question we started with.
The first is [] ==! [] is true, as shown below:
[] ==! []
[].toSring() / /"
Number(' ') / / 0! []// false
Number(false) / / 0
0= =0 / / [] = =! [] to true
Copy the code
The {} = =! {} is false, as shown below:
{} ==! {}
({}).toString() // "[object Object]";
Number("[object Object]") // NaN! {}// false
Number(false) / / 0
NaN! =0 / / {} = =! {} to false
Copy the code
So what does the following code output?
{} + {} // ?
[] + {} // ?
{} + [] // ?
Copy the code
You can try it out by clicking on this link.
Search ikoofe on wechat, and the public account “KooFE Front-end team” releases front-end technology articles from time to time.