JavaScript was originally invented by Brendan Eich from Netscape in March 1996. It was invented by Brendan because of the technological needs in Netscape Navigator 2.0 project. Mr. Eich modeled himself by previous attempts of Nombas company to create a embedded scripting language, eventually he worked with Sun Microsystems on LiveScript, which changed its name just before the premiere. Almost one year later (June 1997) ECMA(European Computer Manufacturers Association) elaborated first version of ECMAScript standards that are primal base of the latest TS39 standards. The funniest part of this story is the part with the keyword Java, which was very popular back then and that’s why they used it instead of Live prefix.

Despite the JS low entry threshold of programming ability and knowledge, you will need a lot of time, patience, practice and commitment to become an expert. At the beginning of my journey with JavaScript I found it very hard to understand the complexities of the ECMA specifications. I really enjoy good jokes and laughter in every day routine and this fact made me think, if there was a way to learn the beautifulness of JavaScript in more funny way than we’re used to. In my life I’ve been asked many technical questions about JavaScript and they were always very formal and focused on some narrow aspects of JS trickiness. I started to wonder if those question were asked in a different way, would they meet my answer?

Then while scrolling down social media I found a JS meme with some funny examples like ‘true is false, NaN is not a NaN or my favourite precision 0.1 + 0.2’. It made me laugh and wonder at the same time, why does it work this way. After some time I made a temporary sheet where I started to document my efforts of understanding the JS’s trickiness and below I would like to share some of them to reveal you the true beautifulness of JavaScript.

 

  • true is false:

This example breaks our human logic because we are comparing two different expressions and the result is true.

!!“false” == !!“true”;  // -> true

!!“false” === !!“true”;  // -> true

This happens because truthy/falsy expresions aren’t real boolean values. Abstract Equality Comparison operator is being described in ECMA docs –

https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison

// true is ‘truthy’ and represented by value 1 (number), ‘true’ in string form is NaN.

true == “true”;  // -> false

false == “false”;  // -> false

// ‘false’ is not the empty string, so it’s a truthy value

!!“false”;  // -> true

!!“true”;  // -> true

  • NaN is not a NaN:

This is another example of illogical comparison – we are comparing seemingly the same type, but as result we got an answer that our expression is false.

NaN === NaN;  // -> false

The specification strictly defines the logic behind this behavior:

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Number, then
    1. If x is NaN, return false.
    2. If y is NaN, return false.

https://www.ecma-international.org/ecma-262/#sec-strict-equality-comparison

 

  • Precision of 0.1 + 0.2 :

This example breaks our human logic because we are comparing two different expressions and the result is true.

0.1 0.2  // -> 0.30000000000000004 

( 0.1 + 0.2 ) ===  0.3;  // -> false

JavaScript uses 64-bit floating point representation, which is the same as Java’s double. The crux of the problem is that numbers are represented in this format as a whole number times a power of two; rational numbers (such as 0.1, which is 1/10) whose denominator is not a power of two cannot be exactly represented. Good example would be a decimal representation of value 1/3. In that case 0.1 real value equals 0.1000000000000000055511151231257827021181583404541015625.

Full description: https://stackoverflow.com/questions/588004/is-floating-point-math-broken

 

  • Tricky arrow functions:

This example is based on ES6 – arrow functions which are simplified function constructions. You can easily create a one line function and return 10 like this:

let f = () => 10;

f();  // -> 10

So what if we would like to return an empty object?

let f = () => {};

f();  // -> undefined

At first I also thought we will get an empty object. This happens because the curly braces are part of the syntax of the arrow functions, so f() will return undefined. It is however possible to return the {} object directly from an arrow function, by enclosing the return value with brackets.

let f = () => ({});

f();  // -> {}

  • [ ] is equal ![ ]

This example as almost all above cannot be taken into normal human thinking. We compare an empty array with negated empty array and as a result we get true.

[] == ![];  // -> true

This happens because the abstract equality operator converts both sides of expresion to numbers to compare them. Both sides become the number 0. Left side is being converted to number instantly without boolean conversion while the right side is being converted to boolean value first because of the negative(logical not) operator.

+[] == +![];

0 == +false;

0 == 0;  // -> true

https://www.ecma-international.org/ecma-262/#sec-logical-not-operator

https://www.ecma-international.org/ecma-262/#sec-abstract-equality-comparison

Those are 5 of my favourite examples that show the real beauty and trickiness of JavaScript. All of them are made this way because of some reason, even if it’s not so obvious at the beginning.

Piotr Jaśkiewicz, 2019

Leave a Reply

Your email address will not be published. Required fields are marked *

© by helloastra 2019