enjoying salad since 1978.

Sunday, February 17, 2008

JavaScript undefined vs. null

I was reading a modern, popular book on JavaScript last night and was disappointed by the handling of null. The author started out doing a lot of checking like:

if (foo == null) {   alert('foo is not set.'); }

Then told the reader that they could just remove the == null because javascript knows you mean "== null"

What?! This isn't why you don't check for equality with null. It's because foo == null doesn't even remotely do what most people think it does in this context.

It's a commonly held belief that uninitialized properties in JavaScript are set to null as default values. People believe this mostly for 2 reasons: 1) foo == null returns true if foo is undefined and 2) authors don't teach JavaScript properly.

A property, when it has no definition, is undefined. Put that way, it's pretty obvious.

null is an object. It's type is null. undefined is not an object, it's type is undefined. That part is less obvious.

The real trouble is that == does type coercion. === checks for both type and value and is the most intuitive form of equality in JavaScript, in my opinion.

I fired up a Jash console to hopefully clear things up for you.

>> window.hello
null
>> window.hello.something
window.hello has no properties
>> window.hello == null
true
>> window.hello === null
false
>> window.hello === undefined
true
>> if (window.hello) { alert('truthy'); } else { alert('falsy'); } // will print falsy.
null
>> window.hello == undefined
true
>> null == undefined
true // there's the rub, sir.
>> null
null
>> undefined
null
>> typeof null
object
>> typeof undefined
undefined

So people write

if (foo == null) {
   foo = "Joe";
}
When what they really mean is
if (!foo) {
   foo = "Joe";
}
If you find yourself with a lot of null checks in your JavaScript, set aside some time and watch Douglas Crockford's "The JavaScript Programming Language" talk on Yahoo Video. It's part 1 of a 3-part series of excellent and enlightening talks.

24 Comments:

Blogger Phoenix said...

A nice help this post was.
Thx for your time.

10:18 AM

 
Blogger Sean said...

Yeah...but your suggested replacement is more ambiguous.

if(!foo){

would be triggered by undefined, null or false.

var bool = false;
alert(!bool);
alert(bool == null);

doing a null check is more specific and tells anyone reading the code that js is looking for 'non value' variables

11:29 PM

 
Blogger David said...

Unfortunately, your session with Jash is rendered pretty hilarious by the fact that evaluating "window.hello" produces "null". What possible reason is there for that? Oh, wait, the source code for Jash basically says the equivalent of if (result == null) print("null")! (Of course, evaluating alert(window.hello) in a browser will say "undefined".)

12:56 AM

 
Blogger LudoA said...

Hi!
Would you mind saying which book it is? Just so I know which to avoid should I buy a JS book.

Either way, thanks for the informative post!

2:46 AM

 
Blogger Steve Jenson said...

@david: truly unfortunate.

9:08 AM

 
Blogger Neha Chachra said...

I totally agree about the Douglas Crockford javascript series. Though I forgot some of it, so your blog was useful to verify that I remembered correctly :)
Thanks :)

12:20 PM

 
Blogger Brian Peiris said...

Thanks for your post, helped me clear up a bit of confusion.

Although, it should be noted that (typeof undefined) evaluates to the string "undefined" and not the special primitive value of undefined.

Yet another inconsistency of the Jash console. ( I'd suggest using Firebug Lite instead :) )

8:40 AM

 
Blogger Brian Peiris said...

I'm halfway through the Douglas Crockford talk and it would seem that most of these types problems could be solved by always using the identity operators [=== and !==], as Douglas mentions.

This would also solve the ambiguity problem Sean mentioned in his comment above. Using (foo === null) instead of (!foo) is clearer and avoids JavaScript's magical behind-the-scenes type coercion.

8:06 AM

 
Blogger DjZoNe said...

Quiet useful article. Thank you :)

3:40 AM

 
Blogger kartick's said...

I have one doubt re4garding this i have somescript like this it's a script of ASP I am unable to handle undefined
can u suggest any thing?
My code is


var fname;
fname=Request.QueryString("fname");
if(fname != "" && fname)
{
Response.Write("Hello " + fname + "!
");
Response.Write("How are you today?");
}

9:36 PM

 
Blogger S said...

This blog helped me a lot. I was writing a script and I had a bug I was trying to track and I couldn't figure out why a certain block of code wasn't being executed until I read this! Unfortunately the bug had nothing to do with this (it was two numbers on the wrong side of a minus), but this did help me understand why the debug block of code was not being entered.

1:40 PM

 
Blogger Ates said...

<< window.hello
null

Wait a minute. Jash seems to be doing something funny there. Isn't an undefined property supposed to be evaluated to "undefined" instead?

Try the same with the Firefox error console:

window.hello
undefined

And with Jash:

<<typeof window.hello
undefined
<<String(window.hello)
undefined

I found the very first example where window.hello results in a "null" inaccurate and misleading and countering the purpose of this article.

10:47 AM

 
Blogger Girish Borkar said...

You summed it up nicely. I watched douglas crockford videos and have collected a list of javascript related videos here.

8:20 PM

 
Blogger linker said...

I suppose that JS "null" is a non-proper replacement for Haskell "Maybe".

"Maybe" in Haskell is a container for a single variable. "Maybe" can hold either a variable or nothing (null).

9:40 PM

 
Blogger Weston Ruter said...

Be careful when testing for "undefined". The "undefined" keyword is actually a variable (at least in Gecko) whose value that can be overwritten; it's not an immutable keyword like "null". So you can do this:

(window.foo === undefined) === true;
undefined = 10;
(window.foo === undefined) === false;
(undefined === 10) === true;

Therefore, it is safer to test for undefined by using typeof:

typeof window.foo === "undefined"

This will always be true if window.foo is not set, even if the "undefined" variable is messed with.

4:38 PM

 
Blogger Attila Szegedi said...

Also might worth be reading: Undeclared, Undefined, Null in JavaScript (disclaimer: I wrote that article last year in response to some widespread confusion over these concepts)

12:02 PM

 
Blogger Zak said...

Good post, it showed me the difference between null and undefined.
However, as you seem to be stressing the small but possibly consequential difference between the two I have to comment on the final example in your post.

I would much rather people use if (foo == null) than if (!foo). The first will do what you expect whereas the 2nd will give some really odd behaviour if foo is not 'null' or 'undefined' and is instead a boolean of 'true' or 'false'.

Good post otherwise.

1:47 PM

 
Blogger Zak said...

whoops missed Seans comment at the top saying exactly what I just did.

1:49 PM

 
Blogger Unknown said...

THANK YOU THANK YOU!!!

I tried for such a long time to get my stupid program to work by using:

if(x==null)

but all I had to do was use:

if(!x)

Gosh I feel stupid. Thanks for your blog.

12:57 PM

 
Blogger Matt Wittemann said...

Thanks for this. There is a lot of bad information out there about checking null values in javascript strings. This was very helpful.

6:24 PM

 
Blogger Matěj Cepl said...

Except, if (!foo) works most of the time pretty well, but in the moment you have optional Boolean argument, it bites you terribly. I have spent half an hour because I used foo == null and switched (under the influence of Crawford’s JSLint) to foo === null. :(

Thanks for this post, I understand why I have wasted all that time.

6:36 AM

 
Blogger Reimer said...

Perhaps I'm missing something but what if foo is number which can be zero. Now if you want to test if foo is null or defined, then if(!foo) doesn't seem the right way

7:39 AM

 
Blogger Brian Peiris said...

@Reimer
This post dealt, mainly, with the difference between undefined and null but you're are right, 0 and the empty string are also falsy.

We can demonstrate JavaScript's boolean coercion with a double NOT (!!) operator:

!!undefined === false
!!null === false
!!0 === false
!!'' === false

*Everything* else is truthy, including the empty array and the empty object:

!!{} === true
!![] === true

!!-1 === true
!!1 === true
!!"bar" === true

etc.

10:57 AM

 
Blogger Munawwar said...

Its two years since this blog was written.But it appeared second in the list on google search.
So I have to clear a misconception (For all those who are going to read this in future).

The undefined object can be mutated in gecko based browsers.
undefined=10 is a valid statement (in firefox).

Try this:
alert(window.foo === undefined); //true
undefined = 10;
alert(window.foo === undefined);//false
alert(undefined === 10);//true

So Weston is right.
typeof window.foo === "undefined" is an error-proof and unambiguous way of confirming a variable undefined.

1:13 PM

 

Post a Comment

Links to this post:

Create a Link

<< Home