Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

Casts contrast many implicit type conversion will be intuitive, the result of the transformation is shown, in line with the conversion of intuitive, according to API can very clearly know the results transformation, but the implicit type conversion will be a lot of metaphor, because the trigger implicit type conversion exist a variety of ways, is easy to ignore in the development process, causes the inexperienced developers are difficult to understand

Implicit type conversion

If you have two different data types, and the need for logical operators (&&, | |,!) Implicit type conversions are triggered by operators of, (+, -, *, /), relational operators (>, <, <=, >=), equality operators (==), or if/while conditions, which are often overlooked

Implicit type conversion rules for ‘+’

The ‘+’ operator can be used not only for numeric addition, but also for string concatenation. Only if both sides of the ‘+’ sign are numbers, we’re adding. When a string is added to any other type using the + operator, it is converted to string for concatenation. In all other cases, it will be converted to number, but undefined will be converted to NaN, and the sum will be NaN

  • If one of them is a string and the other is undefined, NULL, or Boolean, the toString() method is called to concatenate strings. If it is a pure object, array, re, etc., the complex type is converted to a primitive type (the conversion has precedence), and then the operation and concatenation are performed
  • If one of them is a number and the other is undefined, NULL, Boolean, or a number, it is converted to a number for addition, as shown above
  • If one of them is a string and the other is a number, they are concatenated according to string rules.
1 + 1;								/ / 2
1 + '1';							/ / '11'
1 + null; 						/ / 1
'1' + null; 					// '1null'
1 + undefined;				// NaN
'1' + undefined;			// '1undefined'
1 + true;							/ / 2
'1' + true;						// '1true'
1 + false;						/ / 1
'1' + false;					// '1false'
Copy the code

Implicit type conversion rule for ‘==’

It is frequently used in the development process, and the general process of its conversion rules is as follows:

  • If the types are the same, you do not need to perform type conversion

  • If one of the operators is null or undefined, the other operator must be null or undefined to return true, otherwise false is returned

null= =undefined     // true
null= =1 			  		// false
undefined= =1    		// false
Copy the code
  • If one of them is of type Symbol, return false
const symbol = Symbol()
symbol == 2 					// false
symbol == 'symbol'    // false
Copy the code
  • If the two operation values are string and number, the string is converted to number
'1'= =1          		// true
Copy the code
  • If an operation value is Boolean, convert to number
1= =true       			// true
11= =true       			// false
0= =true      				// false
Copy the code
  • If an operation is object and the other is string, number, or symbol, object is converted to its original type and evaluated

The conversion of Object is a bit more complicated than other types because of the concept of metaprogramming, but the tendency of Object is to convert data from reference types to primitive types, with the following priorities:

It first determines whether Symbol. ToPrimitive exists, and if it does, calls it first and returns the data

If not, the methods valueOf or toString on the object are called, and the return value is the result of the conversion to the primitive type

Note: Symbol. ToPrimitive must return the underlying data type, otherwise the console will report an error

const obj = {
  [Symbol.toPrimitive]() {
    return{}}}; obj +1;
Copy the code

Uncaught TypeError: Cannot convert object to Primitive value

The Symbol. ToPrimitive method exists

const obj = {
  [Symbol.toPrimitive]() {
    return 1
  },
  valueOf() {
    return 2;
  },
  toString() {
    return 3}};console.log(obj + 1); / / 2
Copy the code

When there is no symbol.toprimitive method, there are only two valueOf and toString methods, which method will be called first if the object is inclined to convert. If the conversion to Number is preferred, valueOf is called first. If you prefer to cast toString, just call toString

In case of bias to Number type, the data returned by valueOf is preferred. If valueOf returns a non-base data type, toString is continued to be called

ValueOf returns the underlying data type

const obj = {
  valueOf() {
    return 2;
  },
  toString() {
    return '3'}};console.log(obj + 1); // 3, go to valueOf
Copy the code

ValueOf does not return the underlying data type, so we continue with the toString method

const obj = {
  valueOf() {
    // Returns a non-base type
    return {};
  },
  toString() {
    return '3'}};console.log(obj + 1); // '31' takes the toString method
Copy the code

Tends to cast toString, uses data returned by toString preferentially, and continues to call valueOf if toString returns non-base data types

ToString returns the underlying data type

const obj = {
  valueOf() {
    // Returns a non-base type
    return 2;
  },
  toString() {
    return '3'}};// The content is '3' and the toString method is used
document.write(obj);
alert(obj) 
Copy the code

If toString returns a non-base data type, valueOf continues to be called

const obj = {
  valueOf() {
    return 2;
  },
  toString() {
    // Returns a non-base type
    return{}}};// If the value is 2, go to valueOf
document.write(obj);
alert(obj) 
Copy the code

At this point, does the reader wonder what would happen if toString and valueOf both returned non-basic types of data?

Uncaught TypeError: Cannot convert object to primitive value