JS WTF šŸ¦„ with Arrays

Letā€™s ride on some WTF with JavaScript Arrays.

Tiago Ferreira
HackerNoon.com
Published in
4 min readOct 9, 2017

--

[] == ![]

This happens because of precedence and coercion.

Side note ā€” Precedence determines the order from which operators are executed. The highest the precedence the sooner the operation will be performed. For instance, * has an higher precedence than the operator +. As for Coercion, this is JS ability to convert one of the operands (of an operator) to an ā€œequivalentā€ value of the other operand. This happens when the operandsā€™ type are different. For instance, for boolean == integer , the boolean operand will be converted into an integer.

Due to precedence JS executes first the operation ![] and then ==.

The logical NOT operation ![] negates the truthy of [] and returns the boolean false. On a step-by-step:

  1. Evaluate the expression [];
  2. Convert the result to boolean, i.e. ToBoolean([]). By definition the result is true;
  3. Return false, which is the logical negation of true;

We got[] == false.

Now, it comes coercion into play.

Because our second operand is a boolean, the operation is translated into [] == ToNumber(false). ToNumber of a boolean returns 1 when true or 0 when false (see the specification).

We got [] == 0.

By specification, [] == 0 translates into ToPrimitive([]) == 0, which in turn results into the operation OrdinaryToPrimitive([], "number") == 0.

OrdinaryToPrimitive for the parameters Object and "number" runs both methods .valueOf() and .toString() of the Object and returns the result which is not an object. In our case, because [].valueOf() returns an object (i.e. []), the result of [].toString() is returned instead (i.e. "").

We got "" == 0.

Patience. We are almost there šŸ˜…

Now, once the first operand is a string, our operation is translated into ToNumber("") == 0. By definition, an empty string is converted into 0.

We got 0 == 0.

Which is true šŸŽ‰

There you go!

Note: I went as deep I could on this first WTF to let you know how handy JS can be. For now on Iā€™ll try to be more briefly.

.apply()

This ā€œfeatureā€ is brought to you by ECMAScript 5th Edition.

Starting with ES5 we can call Function.prototype.apply() with any array-like object. What this means is that apply()ā€˜s second argument (see definition) needs to have the property length and the integer properties in the range 0ā€¦length ā€” 1.

For instance, the array [6,8] has the property length of 2 and the integer properties from 0ā€¦1 (meaning, [6,8][0] and [6,8][1].) So itā€™s an array-like object (this is a simple explanation, you can read the details here.)

Because all the 4 examples are array-like objects with the property length, apply() will execute the Array function with each value from 0ā€¦length ā€” 1 as its arguments.

For the example {length: 3} it has a length of 3 and apply() will execute Array as follows:

.sort()

This is not a WTF.

This is how sort() works. But we can have fun anyway šŸ˜ƒ

According the specification, sort() sorts the elements of an array according to their string unicode value.

Because the unicode value for first character of 10 (i.e. 1) is lower than the unicode value for the character 2, 10 appears before 2 when ā€œsorting.ā€

I feel funny now!

šŸ”„ .slice()

You may all recall our friend slice() which, according to its specification, ā€œit takes two arguments, start and end, and returns an array containing the elements of the array from element start up to end (end not includedā€.)

The syntax

array.slice(begin, end)

In both our examples, begin = 0.

However, and although both null and undefined represent the absence of a value, the result for end = null has nothing to do with the result for end = undefined.

The reason is ECMAScript Specification.

Which says,

  • if ā€œend is undefinedā€, then ā€œend is arrayā€™s lengthā€.
  • else ā€œtoInteger(end) ā€, which translated into ā€œtoNumber(end)ā€.

By definition, toNumber(null) is 0.

Our statement [1, 2, 3].slice(0, null) is in fact [1, 2, 3].slice(0, 0).

You guessed it. Thatā€™s [].

šŸ» Thank you note: A HUGE thanks to @joaoffalcao for this WTF.

< your WTF >

If you find any WTF that should be here, please let me know šŸ‘

Thatā€™s all for Arrays.

Thanks to :

--

--

Tiago Ferreira
HackerNoon.com

I am helping disrupt the code review process with @reviewpad