Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does "[] + {} === {} + []" evaluate to "true"? [duplicate]

Tags:

javascript

If you open your JS console and type in [] + {} === {} + [] it tells you it's true.

I don't understand why this is. I attempted to look up at how it's parsed.

For [] + {} the + here is the addition operator as operands are both literals. LHS doesn't yield a number through .valueOf() so it performs string concatenation using .toString() on both operands giving us "" + "[object Object]"

For {} + [] the {} is an empty code block and is 'ignored', the + operator here is parsed as the unary plus operator, it converts its operand to a Number. Empty arrays converted to a number become 0

So this is appears to be "[object Object]" === 0 which surely should be false?.

The identity operator checks if the two operands are equal without type conversion. I can't see how this ever coud be true. What part of the story am I missing?

Edit:

I see if you type ({} + []) it parses it as an empty object making the RHS equal to "[object Object]". I looked this up and ( ) is the grouping operator. So perhaps this has something to do with this?

This is not a duplicate of What is the explanation for these bizarre JavaScript behaviours mentioned in the 'Wat' talk for CodeMash 2012?. Answer bullet points 1 === 2 should NOT be true.

like image 962
Mardoxx Avatar asked Dec 13 '16 15:12

Mardoxx


People also ask

Why does [] === [] return false?

Note that === never causes type coercion, but checks for correct types first and yields false if they are not equal! Only if the types are equal, it compares the actual values. So this method of comparison is far more reliable than == .

Why {} === {} is false in JavaScript?

Each object, each {} is distinct. Same applies to arrays, too. Show activity on this post. 2) it does not make any difference whether you use == or === for comparing objects, because comparing them always returns false.

Why is {} [] and []+ {} not same in JavaScript?

Note that {} + [] === [] + {} will not produce the same - again, due to point 3 of the linked answer - the first {} will be interpreted as an empty block, so the left hand side becomes +[] which converts the array to a number, hence the result of the comparison will be false .

What evaluates to true JavaScript?

In JavaScript, a truthy value is a value that is considered true when encountered in a Boolean context. All values are truthy unless they are defined as falsy. That is, all values are truthy except false , 0 , -0 , 0n , "" , null , undefined , and NaN .


2 Answers

The second point in this magnificent answer explains what happens when you "add together" an array and an object.

var result = [] + {};    console.log(result);  console.log(typeof result);

What you get is the string [object Object] because each of the arguments is converted to a string. For an array, that results in calling .join() on it, which in turn, results in an empty string. For Objects, it produces the string "[object Object]" - adding them together leaves the second string.

The same happens on both sides of the comparison - on the right hand side, the order is different but that does not matter. The result will not be the same as point 3 in the answer, for the difference is that there {} + [] is in the beginning of the line, so {} is interpreted as an empty block. In this situation it will (correctly) be interpreted as a plain object notation). The same casting logic will be performed and it will produce the same string as before: "[object Object]"

So, in the end, you are comparing "[object Object]" === "[object Object]" which returns true.

Note that {} + [] === [] + {} will not produce the same - again, due to point 3 of the linked answer - the first {} will be interpreted as an empty block, so the left hand side becomes +[] which converts the array to a number, hence the result of the comparison will be false. However if you test this expression in the Chrome dev tools you will indeed get true. This is because Chrome will auto-wrap your expression in parentheses which forces the initial {} to be interpreted as an object. Checking {} + [] === [] + {} in Firefox or Node REPL or others should produce the "correct" false.

like image 106
VLAZ Avatar answered Oct 08 '22 13:10

VLAZ


    var array = ['test1', 'test2', 'test3']      var emptyObject = {}        console.log(typeof(array+emptyObject));      console.log(array+emptyObject);      console.log(emptyObject+array);      console.log(array+emptyObject === emptyObject+array);        var array = [];      var emptyObject = {}        console.log(typeof(array+emptyObject));      console.log(array+emptyObject);      console.log(emptyObject+array);      console.log(array+emptyObject === emptyObject+array);        var array = ['firstArrayElement', 'secondArrayElement'];      var object = {a:1, b:2}            console.log(typeof(array+object));      console.log(array+object);      console.log(object+array);      console.log(array+object === object+array);        console.log(['a','b']+['c','d']);

When you convert an empty array to string you will receive empty string.

When you convert an object({}) to string you will always receive string: "[object Object]".

Plus operator is not defined for arrays and objects so JS always convert array and object to string when you use plus operator.

like image 26
Krzysztof Raciniewski Avatar answered Oct 08 '22 14:10

Krzysztof Raciniewski