As one JavaScript developer, there are some strange events about JavaScript you should know. Maybe, you have never seen those strange events in JavaScript. But in this post, I just want to sort out the confusing expressions in javascript and the principles behind it.

**Do you know the result of these expressions?**

`1 + '1'`

`1 - '1'`

`'2' + '2' - '2'`

`[] + []`

`{} + {}`

`[] + {}`

`{} + []`

`[] + {} === {} + []`

`{} + [] === [] + {}`

`[+false] + [+false] + [+false]`

`[+false] + [+false] + [+false] - [+false]`

`'1' == true`

`parseInt('infinity') == 0 / 0`

`1 < 2 < 3`

`3 > 2 > 1`

`isNaN(false)`

`isNaN(null)`

`[[][[]]+[]][+[]][++[+[]][+[]]]`

If you want to know the correct answer, paste the expression into the browser’s console and execute it.

The next step is to explain what the results of these expressions are based on.

The key to solving the above problems is to understand three points:

- Operator usage and priority
- The operand data type conversion rule in the context of the operator
- The special case in grammar

`+`

operator

`+`

There are three roles in JavaScript:

- Connection string:
`var result = 'Hello' + 'World'`

- Calculate the sum of the numbers:
`var result = 1 + 2`

- As a unary operator:
`+variable`

In the expression `+`

is the operator (operator), the object of the operator operation ( `Hello`

, `World`

, `1`

, `2`

in the above example) is called operand (operand)

The rule for the unary `+`

operator is: `ToNumber(ToPrimitive(operand))`

, which converts any type into a numeric type.

When the data types of the operands are inconsistent, the conversion is based on the following rules:

- If at least one operand is an object data type (
`object`

), then you need to convert it to a`primitive`

type (`primitive`

), ie string, number or boolean- If the object is a
`Date`

type, then call the`toString()`

method - Otherwise, the
`valueOf()`

method is called first. - If the
`valueof()`

method does not exist or does not return a base type, then call`toString()`

- When an array is converted to a base type, JavaScript uses the
`join(',')`

method. - The result of a simple Javascript object
`{}`

conversion is`[object Object]`

- If the object is a
- After conversion, if at least one operand is a string type, then the other operand needs to be converted to a string type and then the join operation is performed.
- In other cases, both operands are converted to numeric types and the addition is performed
- If both operands are primitive types, the operator will determine that at least one is a string type and performs a join operation. Everything else is converted to numbers and summed

So according to the above rules, we can explain:

- The result of
`1 + '1'`

is`'11'`

because one of the operands is a string, so the other operand is also converted to a string and a string concatenation operation is performed. - The result of
`[] + []`

is`''`

an empty string, because the array is an object type, the result of converting to the underlying type is an empty string, which is still an empty string after splicing - The result of
`[] + {}`

is`[object Object]`

, because the operand has the relationship of the object type, both operands need to be converted to the base type,`[]`

converted to the base type and the result is`''`

,`{}`

converted to the base The result of the type is`[object Object]`

, and the result of the last string concatenation is still`[object Object]`

Next, let’s talk about the notable situation.

- The result of
`{} + []`

is`0`

. Because in this expression, the beginning`{}`

not the literal of the empty object, but is treated as an empty block of code.In fact, the value of this expression is the result of`+[]`

, which is`Number([].join(','))`

, which is`0`

- Even more strange is the expression
`{} + {}`

, which will get different results when executed in different browsers. According to the above example, we can similarly introduce the value of this expression is actually the value of`+{}`

, that is, the final result is`Number([object Object])`

, which is`NaN`

. The result of this implementation in IE 11 is the same, but if you execute it in Chrome, you get the result`[object Object][object Object]`

.

This is because Chrome devtools implicitly adds parentheses `()`

to the expression when executing the code, and the actual execution code is `({} + {})`

. If you execute `({} + {})`

in IE 11, you get the result of `[object Object][object Object]`

- Although we have already made clear that the result of
`[] + {}`

is`[object Object]`

and the result of`{} + []`

is`0`

, if we compare them:`[] + {} === {} + []`

result will be`true`

. Because the relationship of`{}`

following the`===`

on the right side is no longer considered to be an empty code block, but a literal empty object, so the result on both sides is`[object Object]`

`{} + [] === [] + {}`

also an ambiguous result. In theory, the return value of an expression is`false`

, which is`false`

in IE 11, but returns`true`

in Chrome’s devtools. Is the expression being executed in`()`

`[+false] + [+false] + [+false]`

can also be imagined. The result of`+false`

is`false`

converted to the number`0`

, after which`[0]`

is converted to the base type string`'0'`

. So the final result of the expression is`'000'`

`-`

operator

Although the `-`

operator and the `+`

operator look the same, the `-`

operator has only one function, which is a numerical subtraction. It will try to convert non-numeric operands into numeric types. If the result of the conversion is `NaN`

, then the result of the expression can be imagined as `NaN`

. If all the conversions are successful, the subtraction operation is performed, so

`1 - '1'`

actually performs`1 - 1`

and the result is`0`

`'2' + '2' - '2'`

expressions must first follow the execution order from left to right,`'2' + '2'`

is executed in string concatenation, the result is`'22'`

, in the next`'22' - '2'`

calculation, both operands are successfully converted to numbers, and the result is the result of digital subtraction`20`

`[+false] + [+false] + [+false] - [+false]`

expression actually executes`'000' - '0'`

and the final result is the number`0`

`==`

operator

In JavaScript, `===`

called the identity operator, and `==`

called the equality operator. Because of the length of the relationship, here we simply talk about the topic

If the data type of the operand of the `==`

operator is different:

- If one operand is
`null`

and the other operand is`undefined`

, they are equal - If one operand is a numeric type and the other is a string type, then convert the string type to a numeric type and compare
- If an operand is a boolean type, then convert
`true`

to 1, and`false`

to 0 for comparison - If one operand is an object and the other operand is a number or a string, then convert the object to a primitive type and compare

- According to the above rules, when calculating the expression
`'1' == true`

, first convert`true`

to the number`1`

, then the value and string type exist in the expression, and then convert the string`'1'`

to the number`1`

, and finally`1 == 1`

course established - The expression
`parseInt('infinity') == 0 / 0`

actually judging`NaN == NaN`

, such a comparison is a special case, whether in the`==`

comparison or`===`

comparison,`NaN`

will not be equal to anything Or, as long as any operand is`NaN`

, the expression will return`false`

For a more comprehensive comparison of `==`

and `===`

.

The comparison operators `>`

and `<`

also follow similar rules: 1. Compare strings to numbers for comparison; 2. Convert boolean types to numbers and compare them,

- In expression
`1 < 2 < 3`

, first perform`1 < 2`

and the result is`true`

, but in the process of comparing`true < 3`

, you need to convert`true`

to numeric type`1`

, and finally compare`1 < 3`

, return`true`

- Similarly, in the expression
`3 > 2 > 1`

, the final comparison is actually`true > 1`

, which means that`1 > 1`

course returns`false`

`isNaN`

“NaN” is an abbreviation for “Not a Number”. We think that `isNaN`

can be used directly to determine whether a value is a numeric type, but it is not. Because `isNaN`

first forces the parameter to be converted to a numeric type, and then judges. This is not difficult to explain why `isNaN(false)`

and `isNaN(null)`

return `true`

, because both `false`

and `null`

can be successfully converted to the number `0`

, so for `isNaN`

, they are numbers

## Summary

Finally, we use the expression `[[][[]]+[]][+[]][++[+[]][+[]]]`

as the end of the article.

Three operators appear in this expression, respectively

- Member operator:
`[]`

- Unary operator:
`+`

- Operators that act as summation or connection strings:
`+`

- Self-increment operator:
`++`

Based on the operator’s prioritization table , we can determine that the operator’s priority is: `[]`

> unary operator `+`

> `++`

> `+`

So according to the priority we can first calculate the `+[]`

part of the expression and replace this part of the expression with the result of the calculation: `[[][[]]+[]][0][++[0][0]]`

Next we split the expression into three parts: `[ [][[]]+[] ] [0] [ ++[0][0] ]`

. If it is still unclear, the three parts are from left to right:

`[ [][[]]+[] ]`

`[0]`

`[ ++[0][0] ]`

Let’s look at the `[][[]]`

operands in the first part of the first part, the first `[]`

is an empty array, and the immediately following `[[]]`

is the attribute accessor (member operator), within the attribute accessor. The `[]`

will be cast to a string type, and the final result is an empty string `''`

, so the final result of the first operand is actually `[]['']`

, which is `undefined`

, and because of the `+`

operation The rule of the character, the result of the final `[][[]]+[]`

expression is the string `'undefined'`

, then the result of the current stage expression is `['undefined'][0][++[0][0]]`

, ie `'undefined'[++[0][0]]`

Next we solve the third part: `[++[0][0]]`

, I already know that the member operator `[]`

a higher priority than the auto increment operator `++`

, so about the expression `++[0][0]`

, we need to calculate `[0][0]`

, the result is `0`

, then the result of calculating `++0`

is `1`

So the final expression is converted to `'undefined'[1]`

and the final result is `'n'`

## Reference article

- JavaScript addition operator in details
- isNaN()
- The legend of JavaScript equality operator
- What is the explanation for these bizarre JavaScript behaviors mentioned in the ‘Wat’ talk for CodeMash 2012?
- Why is {} + {} no longer NaN in Chrome console?
- Why does JavaScript handle the plus and minus operators between strings and numbers differently?