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 object
if 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.
{} + []
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]
.
[] + []
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.
{} + {}
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]
!
'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 NaN
s 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