JavaScript is a powerful and popular language for programming on the web. In this article you will find a collection of JavaScript’s oddities and well-kept secrets.

NULL IS AN OBJECT

Null is apparently an object, which, as far as contradictions go, is right up there with the best of them. Null? An object? “Surely, the definition of null is the total absence of meaningful value,” you say. You’d be right. But that’s the way it is. Here’s the proof:

alert(typeof null); //alerts 'object'

Despite this, null is not considered an instance of an object. (In case you didn’t know, values in JavaScript are instances of base objects. So, every number is an instance of the Number object, every object is an instance of the Object object, and so on.) This brings us back to sanity, because if null is the absence of value, then it obviously can’t be an instance of anything. Hence, the following evaluates to false:

alert(null instanceof Object); //evaluates false 

REPLACE() CAN ACCEPT A CALLBACK FUNCTION

This is one of JavaScript’s best-kept secrets and arrived in v1.3. Most usages of replace() look something like this:

alert('10 13 21 48 52'.replace(/d+/g, '*')); //replace all numbers with *

This is a simple replacement: a string, an asterisk. But what if we wanted more control over how and when our replacements take place? What if we wanted to replace only numbers under 30? This can’t be achieved with regular expressions alone (they’re all about strings, after all, not maths). We need to jump into a callback function to evaluate each match.

alert('10 13 21 48 52'.replace(/d+/g, function(match) {
	return parseInt(match) < 30 ? '*' : match;
}));

For every match made, JavaScript calls our function, passing the match into our match argument. Then, we return either the asterisk (if the number matched is under 30) or the match itself (i.e. no match should take place).

9. 0.1 + 0.2 !== 0.3

This one is an oddity not just in JavaScript; it’s actually a prevailing problem in computer science, and it affects many languages. The output of this is 0.30000000000000004.

This has to do with an issue called machine precision. When JavaScript tries to execute the line above, it converts the values to their binary equivalents.

This is where the problem starts. 0.1 is not really 0.1 but rather its binary equivalent, which is a near-ish (but not identical) value. In essence, as soon as you write the values, they are doomed to lose their precision. You might have just wanted two simple decimals, but what you get, as Chris Pine notes, is binary floating-point arithmetic. Sort of like wanting your text translated into Russian but getting Belorussian. Similar, but not the same.

FIREFOX READS AND RETURNS COLORS IN RGB, NOT HEX

I’ve never really understood why Mozilla does this. Surely it realizes that anyone interrogating computed colors via JavaScript is interested in hex format and not RGB. To clarify, here’s an example:


<script>
var ie = navigator.appVersion.indexOf('MSIE') != -1;
var p = document.getElementById('somePara');
alert(ie ? p.currentStyle.color : getComputedStyle(p, null).color);
</script>

While most browsers will alert ff9900, Firefox returns rgb(255, 153, 0), the RGB equivalent. Plenty of JavaScript functions are out there for converting RGB to hex.

UNDEFINED CAN BE DEFINED

Strange as it might sound, undefined is not actually a reserved word in JavaScript, even though it has a special meaning and is the only way to determine whether a variable is undefined. So:

var someVar;
alert(someVar == undefined); //evaluates true

So far, so normal. But:

undefined = "I'm not undefined!";
var someVar;
alert(someVar == undefined); //evaluates false!