We will see some other quirks and pitfalls here

[object Object]

We can get the [object Object] if we try to console log a object while trying to concat a string with it.

const obj = { val: 32 };

console.log(obj); //prints { val: 32 }
console.log(obj + 'A'); //prints [object Object]A

Internally JS tries to convert obj into a string by doing obj.toString() resulting in [object Object] !

Now what exactly does it mean ?

The first is object (with a small o), this shows the type tag. JavaScript by default tags every datatype as objectif its not a primitive type like number or string.

The second one is Object (with a capital O), this is the constructor name of the object.

And yes array is a type of object ! Anything not primitive is a type of object;

const arr = [1, 2, 3, 4, 5];
const str = "Nexus";

console.log(typeof arr); //prints object
console.log(typeof str); //prints string

String is a primitive type in JS but array is not, therefore array is a type of object !


Coercion in JavaScript (Implicit Type Conversion)

If there is a type mismatch JS will automatically convert the types as necessary implicitly without telling the user.

  1. {} + []
console.log({} + []); //prints [object Object]

This is [object Object] because [] is an empty array, JS converts it to a string which results in an empty string i.e. [] becomes "" this ! Now {} is an empty object, similar to the array JS converts it too to a string, and we already saw what happens if we convert an object to a string, it becomes [object Object]. Therefore, the whole expression becomes "" + [object Object] resulting in [object Object].

  1. [] + []
console.log([] + []); //prints "" <- nothing (empty string)

This results in an empty string ("") ! As discussed before JS converts an empty array ([]) to string which results in an empty string (""), therefore the whole expression becomes "" + "" which results in a "" (empty string). Nothing is logged on the console.

  1. {} + {}
console.log({} + {}); //prints [object Object][object Object]

This results in [object Object][object Object] ! Same logic, an empty object converted to string results in [object Object] and the whole expression becomes [object Object] + [object Object] which results in [object Object][object Object] !

  1. '5' + 1 = 51 but '5' - 1 = 4 (YEP THATS THE FAMOUS MEME ON JS) !

This is also result of corec……very hard to spell, I will just say implicit conversion its way easier ! Anyways, lets see this in action !

console.log('5' + 1); //prints 51
console.log('5' - 1); //prints 4

If + is applied and either side is a string, JS will implicitly convert everything to string and perform concatenation ! '5' + 1 ? 1 is converted to a string and concatenated to '5' resulting in 51.

But on the other hand, if there is -, * or /, JS will convert the string into a number and perform arithmetic operation. In our case '5' - 1, '5' gets converted into a number and then it substract 1 from it, the result is a number i.e. 4 !

😩 I HATE JS SO MUCH !

Before moving on lets see some more number coercion:

console.log('5' + '2' + '1'); //521 (string)
console.log(true + '5'); //true5 (string)
console.log(true + true + '5'); // 25 (string) [true + true = 1 + 1 = 2 then 2 + '5' = "25"]
console.log('5' * '2' + '1'); //101 (string) [5 * 2 = 10 + '1' = "101"]
console.log('5' * '2' + 1); //11 (number) [5 * 2 = 10 + 1 = 11]
console.log('5' - true); //4 (number) [5 - 1 = 4]
console.log(1 + 2 + '5'); //35 (string) [1 + 2 = 3 then 3 + '5' = "35"]

== vs === Loose Equality vs Strict Equality

  • Loose Equality (==) : tries to implicit convert and equate values.

Lets see through example:

console.log('5' == 5); //true
console.log(false == 0); //true
console.log(null == undefined); //true
console.log([] == false); //true
console.log([] == 0); //true

Implicitly converts values (coercion) and equates them. Not the ideal kind of equality operator.

  • Strict Equality (===) : Matches for exact values without type conversion ! The “yes you will use this one” type of operator. Unlike loose equality, it does not tries to implicitly convert types. It checks for exact value and type too !
console.log('5' === 5); //false
console.log(false === 0); //false
console.log(null === undefined); //false
console.log([] === false); //false
console.log([] === 0); //false
console.log(5 === 5); //true

NGL I don’t know a single scene where I will use == instead of ===.


typeof null === "object" is true

LONG STORY SHORT : ITS A BUG ! 🐞 , In the creation of JavaScript this was a bug which when found later was not fixed because fixing it will cause codebases to cause issues who are using this.


NaN === NaN is false

NaN stands for “Not a Number” ! But…

console.log(typeof NaN); //number

NaN shows up when something meaningless or invalid happens like:

0 / 0; //NaN
undefined + 1; //NaN
"xyz" / 2; //NaN

According to the IEEE 754 standard, NaN is not equal to any value even itself. NaN represents an invalid or un-representable number. Therefore its like saying “NaN === NaN, these 2 NaNs can be any type of invalid, I don’t know if they are equal or not”.

Why typeof NaN === number is true ?

JavaScript uses IEEE 754 standard for all its numeric types. An int is a number and a float too is a number.

So is NaN part of this system but representing it is pointless according to JS ! At this point even I am confused what I am doing with my life documenting this !

Long story short NaN is a number because its in the same numeric system JS uses but its not representable !


[1] + [2] = 12

Why ? Same core…..coeri…..IMPLICIT TYPE CONVERSION ! I could never get that to spell right !

Anyways very simple, JS sees [1] and [2], it says lemme convert them to string and we get "12" ! That’s it !

Few more examples:

[1,2] + [3,4]     // "1,23,4"
[10] + 5          // "105"
[true] + [false]  // "truefalse"
[{}] + []         // "[object Object]"

FINAL THOUGHTS

I know JS, this is just the tip of the ICE-BERG, there must be many more quirks apart from these but this is all I have got, at least for now…

Check out other JS quirks here: Qurik Index