Implicit conversion in Js is often a pain point in front-end development. In daily development, we probably know the concept of implicit conversion for different data types in different operations. So, what are the rules for implicit transformations, and what are the scenarios for implicit transformations down to the nitty-gritty? With doubt, I went through MDN and sorted out some basic things.

  • Primitive type conversion ([string, number, Bigint, Boolean, NULL, undefined, symbol]), usually using the conversion function string, number, Boolean
  • When an object is converted to its original value, the function ToPrimitive is called, depending on the operator and context
  • When the conversion type is expected to be Number or the default value, try converting valueOf to toString in turn
  • When the expected value is String, try toString and valueOf in turn
  • The presence of the [Symbol. ToPrimitive] method interferes with the intended conversion
  • The original symbol value cannot be converted to a string or number, so it must be converted to its wrapper object and then converted to a string by calling the toString() method
Symbol(1) + 1  // TypeError: Cannot convert a Symbol value to a number

Symbol(1) + 'hello' // TypeError: Cannot convert a Symbol value to a string

Symbol(1).toString() + 1 // "Symbol(1)1"
Copy the code

Symbol.toPrimitive

The built-in Symbol value, which exists as a function value attribute of an object and is called when an object is converted to the corresponding original values (expected to be String, number, and default). Parameter hint, indicating the expected type of the original value to be converted to

const object1 = {
  [Symbol.toPrimitive](hint) {
    console.log(hint)  // number, default, string
    if (hint == 'number') {
      return 42;
    }
    return null; }};console.log(+object1);
console.log(object1);
console.log(1 + object1);
console.log(String(object1));

console.log(! object1)// No hint value is printed
Copy the code

The impact of single operators on implicit conversions

Unary operation (+/-)

  • Expected transfer number
+undefined //NaN
+null / / 0
+'1' // -1+ []/ / 0+ {}//NaN
+false / / 0
+true / / 1
+Symbol(1).toString() // NaN
+(() = > {}) // NaN
+Date(a)// NaN
+new Date(a)/ / 1586502202192
+Infinity // Infinity
+NaN // NaN
Copy the code

Bitwise not (~)

  • Expected transfer number
  • The bitwise non-operation on any number x results in -(x + 1)
~undefined / / 1
~null // -1
~'1' / / 0~ []// -1~ {}// -1
~false // -1
~true / / - 2
~Symbol(1).toString() // -1
~(() = > {}) // -1
~Date(a)// -1
~new Date(a)/ / - 1662234207
~Infinity // -1~ -Infinity // -1
~NaN // -1
~0 // -1
Copy the code

Logic (!)

  • Expect to turn a Boolean
!undefined // true
!null // true
!'1' // false
!' ' // true! []// false! {}// false
!false // true
!true // false
!Symbol().toString() // false
!Symbol(a)// false
!(() = > {}) // false
!Date(a)// false
!new Date(a)// false
!Infinity // false
!NaN // true
Copy the code

Increasing (+ +) | decreasing (-)

  • Expected transfer number
let a = [], b = {}, c = (a)= > {}, d = null, e = false, f = '1'
a++ / / 1
b++ // NaN
c++ // NaN
d++ / / 1
e++ / / 1
f++ / / 2
Copy the code

Implicit conversions in expressions

Plus (+)

The addition operator is used to sum values or concatenate strings.

  • String concatenation is expressed when there is a string in the context
0 + '1'  / / '01'
'0' + null // '0null'
'0' + undefined // '0undefined'
'0' + true // '0true'
'0' + Symbol(1) // Uncaught TypeError: Cannot convert a Symbol value to a string
Copy the code
  • When there is no string context, the original data type is expected to be converted to Number, the non-original data type is expected to be converted to String, and the hint parameter of toPrimitive is default
0 + null / / 0
0 + undefined // NaN
1 + Infinity // Infinity
1 + false / / 1
0 + true / / 1
1 + Symbol(1) // Uncaught TypeError: Cannot convert a Symbol value to a number
1 + null / / 1
undefined + null // NaN
false + null / / 0
true + null / / 1
1 + (() = > {}) / / "(1) = > {}"
1 + function a() {} // "1function a() {}"
0 + {} // "0[object Object]"
{} + undefined // "[object Object]undefined"
null + {} // "null[object Object]"
{} + (() = > {}) //"[object Object]() => {}"
{} + [] // "[object Object]"
[] + undefined // 'undefined'
[] + null // 'null'
[1] + 2 / / '12'
[] + (() = > {}) / / "() = > {}"
Copy the code

Subtract (-) | multiply (*) | in addition to (/) yu (%) | o | power (* *)

  • Expected transfer number
0 - null / / 0
0 / undefined // NaN
1 % Infinity / / 1
true ** false / / 1
undefined * null // NaN
1 - (() = > {}) // NaN
0 * {} // NaN
{} / (() = > {}) // NaN
{} % [] // NaN
[2] * *2 / / 4
[1.2] - {} // NaN
Copy the code

Bitwise and (&) | bitwise or (|) | the bitwise xor (^) | left moves to the right (< <) | symbols (> >) | unsigned right shift (> > >)

  • Bitwise operands after expected conversion to number

The Bitwise operators treat their operands as a sequence of 32-bit bits (0 and 1). All the operands of the Bitwise operators are converted to signed 32-bit integers of the form two’s complement.

14 & {} 
// NaN = 00000000000000000000000000000000
/ / 14 = 00000000000000000000000000001110
//  14 & 9 = 00000000000000000000000000000000 = 0

14 | - 1
/ / - 1 = 11111111111111111111111111111111
//  14 | -1 = 11111111111111111111111111111111 = -1

14 ^ true 
/ / 1 = 00000000000000000000000000000001
//  14 ^ 1 = 00000000000000000000000000001111 = 15

14 << 4
/ / 14 < < 4 = 00000000000000000000000011100000 / / 2 * * * * 6 + 2 * 7 + 2 * 5 = 224

14 >> Date(a)// 14 >> NaN = 00000000000000000000000000001110 // 14
// 14 >> new Date() = 0 // 0

14> > > [2]
/ / 14 > > = 00000000000000000000000000000011/2/3
Copy the code

Equal (==) and unequal (! =)

  • The two operands are converted to the same type and compared
  • For relational operators (such as <=), the operands are converted to their original values so that they are of the same type and then compared.
  • A non-primitive type of the same type that compares addresses in memory
false= = []// true
'[object Object]'= = {}// true
(function a() {}) > = ({})// true
[1] = =1   // true
NaN= =NaN  // false
{} != NaN  // false[] [] = =// false, memory address is different= = {} {}// false, memory address is different! [] [] = =// true, hint is number -> false == 0 -> 0 == 0! = = {} {}// false, false == NaN -> 0 == NaN
Copy the code

What do you know about implicit conversions? Implicit conversions don’t know how many more!