Skip to content

thinker3197/Why.js

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 

Repository files navigation

Why.js

JavaScript is not a perfect language, but it's powerful and important. In the past couple of years there have been a lot of infamous talks like this & this that exposed the weird ways in which JavaScript behaves at certain instances. Being the single most popular language on the web right now , it's really common for new developers to fall for it's bizarre behaviour. This repositry aims to highlight those behaviours and demystify why these behaviours occur.

Preface

Many of these WATs occur in JavaScript due to properties such as type coercion and evaluation methodology of == & === operator. The == and === operators evaluate an expression using the abstract equality comparsion algorithms and the strict equality comparison algorithm. JavaScript is a weekly typed language. This means that varibales can automatically be changed from one type to another while evaluating an expression. Although this is a very powerful feature of the language, it might give rise to some unconventional situtaions.

WATs

1. Equality of empty arrays

> [] == []
false

On first look, it sounds ridiculous. An empty array is not equal to itself? But this is not what the above statement actually means. Arrays are stored by references in JavaScript and JavaScript double equal operator returns true only when you're comparing same instances of same type. The comparison above actually asks that, "Is an instance of empty array equal to instace of another empty array?", which is defenitely false. The above statement is similar to

> var a = [];
undefined
> var b = [];
undefined
> a == b
false

a and b are references to two different locations in memory, hence the result is false. However, if the both the array instances have been same, like the one below then answer below would have been true.

> var a = b = [];
undefined
> a == b
true

2. Equlaity of empty array and NOT empty array

> [] == ![]
true

Before understanding what is happening above, we need to understand the concept of truthy and falsy in JavaScript and how the ! (logical NOT) operator works. Values such as false, null, undefined, NaN, 0, '' and "" are considered as falsy. Other values like true, {}, [], "foo" etc. are considered truthy. The ! operator on the other hand is defined for boolean values only. Any other data type will automatically be coerced into it's coresponding boolean value when operated with ! operator. Here, ![] evalutaes to false and the comparison actually becomes

> [] == false
true

Isn't that supposed to be false, since empty arrays are truthy? That's right but the double equal operator evalutes expression on certain rules. We're trying to compare an object with a boolean value and JavaScript will implicitly convert the operands to Number type. Number([]) is 0 and Number(false) is also 0, which evaluates to true since zero is equal to zero.

3. Empty array plus empty array

> [] + []
""

It might look like the sum of two arrays will concatinate them and hence on adding two empty arrays one might get another empty array. But that's not the case in JavaScript. As stated in the ECMA language specification - The addition operator either performs string concatenation or numeric addition. Hence, the + is not defined for arrays and JavaScript will implicitly convert arrays into their string eqvuilent and concatinate them. The above expression will become similar to

> [].toString() + [].toString()
""

Concatination of two empty strings yeilds another empty string and hence the above statement is valid.

4. Empty array minus empty array

> [] - []
0

This case is similar to the previous one. The - operator is not defined for arrays or strings. Hence JavaScript will implicitly convert the arrays into their corresponding number type. Coercion of empty array into number type yeilds 0. The above expression is same as

> Number([]) - Number([])
0

Zero minus zero is obviously zero, which makes sense.

5. Weird array equal weird string

> [null, undefined, []] == ",,"
true

This is quite weird. When we try to compare an non-empty array with a string, Javascript coerces each array element into string and then joins them by commas. Stringification of null, undefined & [] gives an empty string. Hence the expression [null, undefined, []].toString() yeilds ",,".

6. Plus empty array

> + []
0

That's actually not WAT. In Javascript and unary plus operator is used to expicitly convert the object into number type. So the above statement is similar to

> Number([])
0

7. Empty array plus empty object

> [] + {} 
"[object Object]"

You might have guessed this one. As seen in 3, JavaScript will coerce the array and the object into string and then concatenate them. The default conversion for object type to string is [object type], where type is the type of object. There are different type of objects in JavaScript like Object, Function, Array, RegExp etc. In this case it's Object.

> "" + "[object Object]"
"[object Object]"

8. Empty object plus empty array

> {} + []
0

Wait! Didn't we just said that JavaScript coerces object and array to string on plus operator? This is actally a bizzare edge case of javascript. The JavaScript compiler understands this statement a bit diffrently. It considers {} as an empty code block and + [] as another statement. We saw + [] equates to 0 which is why the above expression evaluates to 0.

9. Empty object plus empty object

> {} + {}
NaN

This one is similar to the example above. Explicit conversion of an empty object into number type yeilds NaN.

10. The null and zero

> 0 < null
false
> 0 >= null 
true
> 0 == null 
false

Well, that's frustrating. JavaScript double equal operator and the relational operator are based on the abstract equality comparison algorithm and the abstract relational comparison algorithm. It's just a fancy set of rules to evaluate an expression. When we compare 0 and null using relational operators, JavaScript coerces null into it's primitive number type. When using relational operators the comparison is similar to

> 0 < Number(null)
false
> 0 >= Number(null)
true

null when converted to number type yeilds 0 which explains evaluation of the above statements. However with the == opeartor, such a comparison dosen't fall into any category of rules defined for evaluation of expression by == operator. Neither 0 nor null gets coerced and by rule if such a case occurs where the comparison dosen't fall into any category, false is returned.

11. Math.min is greater than Math.max

> Math.min() > Math.max()
true

A lot of programming languages define global maximum and minimum values and so does JavaScript, but not with Math.max() or Math.min(). They are instead used to return maximum and minimum values within a group of numbers. When these functions are called without arguments, Math.max() returns Infinity and Math.max() returns -Infinity.

> Math.min(1, 2, 3, 4)
1
> Math.max(1, 2, 3, 4)
4

JavaScript employes Number.MAX_VALUE and Number.MIN_VALUE for this task and they work as expected.

> Number.MIN_VALUE < Number.MAX_VALUE
true

Glossary

  • coercion - Also type-conversion Type conversion (or typecasting) means transfer of data from one data type to another.
  • falsy - In JavaScript, a falsy value is a value that translates to false when evaluated in a Boolean context.
  • truthy - A truthy value is a value that translates to true when evaluated in a Boolean context.

About

Demystifying the WATs of JavaScript 🕵

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published