Here’s a meme to start with:

Ahem… This is probably a topic that every JSer can’t get around.


In my foundation for JavaScript | in a separate note, I simply introduced the original type of conversion to each other.

In this article, we will focus on the automatic conversion mechanism of types and summarize the error prone points.

The structure of the article is as follows:

  • Primitive type conversion
    • Converted to Boolean
    • Comparison operator
      • Equality operator
      • Relational operator
    • Four operators
  • Object to the original value
    • ToPrimitive
    • Further conversion




Primitive type conversion

In most cases, operators and functions automatically convert the values assigned to them to the correct type. For example, an alert automatically converts any value to a string for display, and an arithmetic operator converts a value to a number.

If, in some cases, we want to explicitly convert the value to the desired type, we can do this manually. (see this part of the foundation for JavaScript |)

Manual conversion is controllable, as long as we master the right way, usually will not be a big problem. But automatic conversion is sometimes very convenient, and sometimes it’s more of a pain in the neck, which is probably one of the black spots in JavaScript’s early design history. But as long as you code and remember the rules, it’s not that hard.

In JavaScript, type conversions generally fall into one of three categories:

  • Boolean value (Boolean)
  • Turn to number
  • To string (string)

Let’s consider it case by case:

Converted to Boolean

In terms of the complexity of the case that we’re going to talk about, this is the easiest case.

After all, it’s generally intuitive and doesn’t require much memorization.

When a condition is evaluated (for example, if), if the result of a conditional evaluation is not of Boolean type, a cast occurs to change the result to Boolean type.

All values except undefined, null, false, NaN, ”, 0, -0 are converted to true, including all object types.

It should be noted that if(value) and if(value == true) are not the same logic, and the results can be different. Students with other language backgrounds can easily fall over on this question (read on for more details).


Comparison operator

JavaScript comparison operators fall into two categories.

One is the equality operator:

  • Equal (= =)
  • Not equal to (! =)
  • Strict/consistent equality (= = =)
  • Strict/consistent not equal (! = =)

There are also relational operators:

  • Less than (<)
  • Greater than (>)
  • Less than or equal to (< =)
  • Greater than or equal to (> =)

The result of the comparison will return true or false.

Where, only ===! == Two types that do not cast on both sides of the comparison.

This is why standards recommend using these two symbols in preference for equality, except where different types of variables are allowed.

For other comparison operators, fancy conversions take place.

Equality operator

For variables x and y that use the converted comparison operator, there are roughly the following judgment rules (take == as an example) :

Note: In this figure, transposition of the positions of the variables at both ends of == gives the same result.

It can be seen that the comparison between two different types is mostly the comparison of “numerical size”.

Note that Boolean comparisons are also converted to number.

If (value == true) returns false. If (value == true) returns false.

Boolean(value) automatically converts if(value) and if(value == true) automatically converts if(value == true).

More special points:

  • fornullandundefinedWhen we are not strict, we can be equal to each other but when we are strict, we can only be equal to ourselves
  • NaNNot equal to any value, including itself
  • NaNThe magnitude is zero compared to any valuefalse
  • Positive zero equals negative zero
  • For equality comparisons between objects, whether references to two variables are the same (whether strictly or not) is determined.
  • number,string,booleanStrict equality is recommended for all types of equality (again)

One last quick question: are ’42’, String(42), and new String(42) equal?

’42’ (String), String(42) (String) and New String(42) (object), strings and objects are different.

’42’==’42’ (strings equal) is true

New String(42) == New String(42) (objects equal) is false.

Relational operator

The relational operator compares the size of two operands:

  • A comparison of numbers is, of course, a mathematical comparison
  • The comparison between strings followsString comparison algorithm, using The Unicode sequence size (review:'42' < '7'fortrue)
  • For two operands of different types, if the comparison is between a string and a number, if the string can be converted tonumberType, is converted tonumberA comparison between types, otherwise returnedfalse
  • booleanThe type is converted tonumberType (but what does this really mean in practice 🐴? For programmers who don’t code properly?)

Use relational operators to compare sizes between the same types! You need to wake up.

Why null <= 0 and NULL >= 0 are both true and null == 0 is false

Because null <= 0 passes! (null > 0), I find no evidence)


Four operators

Mathematics often automatically converts primitive objects to number. This may seem like a bit of a “trick”, but this is mainly because the web and browser environment often has strings and other types of numbers, so this automatic conversion simplifies our code somewhat. And we don’t have to think about whether it’s a string or a number when we receive a value.

However, of the four operators, the difference between the addition operator + in binary operations is the first easy pitfall for beginners.

For the binary operation of the addition operator:

  • If one side of the operation is a string, the other side is also converted to a string
  • If a party is neither a number nor a string, it is converted to either a number or a string according to its own rules

Large puzzle scene:

1 + '1'     / / '11'
true + true / / 2
4 + [1.2.3] 41, 2, 3 "/ /"
Copy the code

The first two are easier to understand, but the third example, 4 + [1,2,3], deals with the rules for converting objects to primitive types, which I’ll explain below.

Here’s another example:

'a' + +'b' // "aNaN"
Copy the code

Analyze:

  1. The first is+'b'Want to put string'b'convertnumbertype
  2. because'b'Is not a numeric string, so the result of the conversion isNaN(noteNaNIs belong tonumberType definition scope, do not think of it as a string)
  3. And then there’s astringType +numberType expression'a' + NaNthe
  4. According to the rules, willNaNConvert to string'NaN', and then string concatenation, get'aNaN'

The other operators are simple: as long as one side is a number, the other side is converted to a number.

4 * '3'     / / 12
4 * []      / / 0
4 * [1.2]  // NaN
Copy the code


Object to the original value

As mentioned in the previous examples, objects also participate in the operation of the operator, and they also have certain conversion rules.

ToPrimitive

The conversion of an object to a Primitive (Primitive) value is done by a number of built-in functions and operators that automatically call the built-in [[ToPrimitive]] function, which uses a Primitive value as its return value.

It comes in three types (or “hints”) :

  1. string"

    An object-to-string conversion occurs when we perform an operation on an object that expects a string, such as alert() :

    // Output objects
    alert(obj);
    
    // when using an object as a property key
    something[obj] = 42;
    Copy the code
  2. "number"

    When we expect to do math, an object-to-numeric conversion occurs:

    // Explicit conversion
    let num = Number(obj);
    
    // Math operations (except binary addition)
    let num = +obj; // unary addition
    let delta = date1 - date2;
    
    // Less than/greater than comparison
    let isGreater = date1 > date2;
    Copy the code
  3. "default"

    In a few cases, the caller is not sure of the type he expects, in which case the “number” type is mostly treated.

    // Binary addition
    let total = obj1 + obj2;
    
    // The comparison operator
    if (user == 1) {... };Copy the code

    The specification explicitly describes which operator uses which implication. A very small number of operators, even though they are built-in operators, “don’t know what to expect” and use the “default” implication.

Typically for built-in objects, “default” implies the same treatment as “number” (except for Date objects, which toString()), so in practice the last two are usually combined.

To make the transformation, JavaScript executes the methods that call the object in the following order:

  1. ifobj[Symbol.toPrimitive](hint)If it exists, it is called.
  2. Otherwise, if the implication is"string"And try totoString()andvalueOf()
  3. Otherwise, if the implication is"number"or"default"And try tovalueOf()andtoString()
  4. ifvalueOf()Is called if the converted value is still not the original typetoString()

In any case, [[ToPrimitive]] ensures that the converted object returns an original value, otherwise an error will be reported.

We can go back to our previous example:

4 + [1.2.3] 41, 2, 3 "/ /"
4 * []        / / 0
4 * [1.2]    // NaN
Copy the code
  • For the first row
    1. [1, 2, 3]isArrayIn object,defaultThe implication is downvalueOf()Method that still returns an object, so no
    2. Next, call[1, 2, 3]thetoString()Method, return'1, 2, 3'string
    3. digital4With the string'1, 2, 3'Add them together into strings and get the result:'41, 2, 3'
  • The second line
    1. []Is an empty array, called similarly to the example in the first linevalueOf()Call after failuretoString(), returns an empty string' '
    2. digital4And empty string' 'Multiply, empty string' 'Convert to numbers0, the results for0
  • The third line
    1. Same thing with the numbers4With the string'1, 2,'Multiplication,'1, 2,'It can’t be converted to a legal number, so it becomesNaN, is still equal toNaN
    2. It can be extrapolated that, in the case of a unit prime, the result will be a number multiplied by the number of pairs of elements


Further conversion

However, the converted original value is, of course, subject to further conversion. For example, here is a custom object:

let obj = {
  toString() {
    return "42"; }};Copy the code

If it is required to convert, the toString() method is called to convert to the initial value of “42”.

If the context is math, the string can continue to be converted to numbers automatically:

alert(obj * 2);  // "42" * 2 => 42 * 2 => 84
Copy the code


conclusion

I don’t know if you read all of them, or how much you remember (🐴?). “, but remembering these rules can be helpful in understanding the nature of JavaScript (and even more helpful in dealing with weird interview questions). At least make clear these, will not be these trivial things interrupt the writing of the code, to repeatedly search not necessarily reliable answers, also not afraid of others asked when they also know a little, say a wrong answer.

For example, I skimmed these parts at the beginning of learning JavaScript, but later I realized the importance of these trivial knowledge and came back to make a complete summary. If you can, it’s best to reread these points over and over again until you remember them, or to take notes of them yourself.

My personal study notes (⭐) are also available in an online preview if this article is helpful (the Internet may be a little slow without a ladder).