« Back to home

Some More JavaScript Weirdness

JavaScript is a pretty fun language with many "weird" behaviors that make developers want to kill themselves. Some behaviors are quite common like variable hoisting or global scope pollution, some are almost unknown to the majority of frontend developers. Below is the list of weird JavaScript features that I know of (and it's certainly not the complete list):

Primitive vs Object

JavaScript primitives are not instances of the associating object types even though they look like so. For example:

var test = "test";
String.prototype.testFunction = function() { return 0; };
console.log(test.testFunction());  // 0

// but...
console.log(test instanceof String);  // false
console.log(test === new String("test"));  // false

So be careful when using String or Number objects. Use primitives wherever possible unless you know what you're doing.

Arrays

Arrays are also objects and their lengths are calculated as the last array index plus 1. So don't do this:

var arr = [1, 2];
arr[4] = 3;
console.log(arr.length);  // 5

Also it leaves "holes" inside the array which causes some array methods stop working:

var arr = [1, 2];
arr[4] = 3;  // [1, 2, undefined, undefined, 3];

for (var i = 0; i < arr.length; i++) {
  // TypeError: Cannot call method 'toPrecision' of undefined
  console.log(arr[i].toPrecision(2));  
}

Array.prototype.sort defaults to the lexicographical comparison function:

[11, 3, 2].sort();  // [11, 2, 3]

Therefore always pass in a comparison function when calling sort():

[11, 3, 2].sort(function(a, b) { return a - b; });

typeof

Don't rely on typeof for logic control other than checking for undefined. It outputs some strange stuff:

typeof null;  // "object"
typeof NaN;   // "number"
typeof [];    // "object"

Number

All numbers in JavaScript are IEEE_754 64-bit floating point values which use 53 bits as the mantissa. That means the largest integer you can have is 2^53, not 2^32 or 2^64 like in C or Java. Any operation that stretch beyond the largest or smallest integer will be ignored:

var x = Math.pow(2, 53);
x === x + 1;  // true

Unlike arithmatic operators, bitwise operators only work with int32, so:

var x = Math.pow(2, 53);
x / 2;  // 4503599627370496
x >> 1;  // 0

The examples above are taken from this SO answer.

Truthy and falsey

false, 0, "", null, undefined and NaN evaluate to false. The rest are true. However, the fun starts when we compare those value:

false == 0;         // true
false == "";        // true
0 == "";            // true
null == false;      // false
null == null;       // true
undefined == false; // false
null == undefined;  // true
NaN == false;       // false
NaN == NaN;         // false
1 == true;          // true
[0] == true;        // false

That's why the triple equal operator (===) exists. Always use strict comparison to avoid punching yourself when writing JS code.

If you think you know JavaScript well enough, take this quizz. I only got 11/37 :(

Comments

comments powered by Disqus