Thursday, March 24, 2011

Why ==null, Not ===null

Sometimes in RightJS source code you might see a thing like this

if (value == null) {
// ...
}

And as every JavaScript optimization tutorial tells you to use '===null' instead of '==null' and JSLint yells at you when do otherwise, people immediately try to change it to the "right" way.

Meanwhile there is a pretty good case when it is much better to use '==null' than '===null'.

The thing is, that in JavaScript we have this ugly thing called 'undefined', which is quite clunky and often weird in use. Like say you might have a piece of code like that

var hash = {a: undefined};
console.log(hash.a); // -> undefined
console.log(hash.b); // -> undefined

console.log('a' in hash); // -> true
console.log('b' in hash); // -> false

Which is a bit strange. So, it is quite often, people use 'null' to predefine keys in hashes and then need to check whether a certain value is not 'null' or 'undefined', kinda like this

if (value !== null && value !== undefined) {
// ...
}

Another case is that the 'null' thing is an object in JavaScript and sometimes you might need to check if a variable is a plain type value, you go with things like that

if (
typeof(value) !== 'object' &&
value !== null && value !== undefined
) {
// ..
}

There are lots of cases where you need this double check. You also should keep in mind the fact that 'undefined' is a variable in JavaScript and someone actually can define a variable named 'undefined', and in general case you'll need to handle that too. Well, you get the ugly picture.


So, what about that '==null' business anyways?

The trick is that '==null', unlike other boolean comparisons (for example '==true'), returns 'true' only for 'null' and 'undefined' values.

null == null;      // -> true
null == undefined; // -> true

null == false; // -> false
null == ''; // -> false
null == 0; // -> false

Which basically means that you can use value == null instead of

value === null || value === unefined

More of that, except being more compact, 'value == null' also will be protected from 'undefined' replacements, and the browser also won't perform a variable name lookup, because null is a keyword and there is nothing besides it. Which will make the things faster.

How much faster? Let's see. I cranked this little script and run it in FF4

function test1() {
var i=0, t = new Date(), v1 = null, v2 = undefined, r;
for (; i < 100000; i++) {
r = v1 === null && v1 === undefined;
r = v2 === null && v2 === undefined;
}
console.log(new Date() - t);
}

function test2() {
var i=0, t = new Date(), v1 = null, v2 = undefined, r;
for (; i < 100000; i++) {
r = v1 == null;
r = v2 == null;
}
console.log(new Date() - t);
}

console.log('--');
10..times(test1);
console.log('--');
10..times(test2);

And here is the result

--
22
24
23
23
23
23
23
23
24
23
--
2
1
1
1
1
1
1
1
1
1


Well, that's the whole story. Think you can put it in a good use :)

No comments: