Variable hoisting in JavaScript and why you should declare variables at the top

I was recently forwarded an article called JavaScript Adolescence. Go read the article because it's a good one, for the most part. Done? OK. There's some great stuff to think about, and I especially like his thoughts on inline regex's, single letter variable names, and truthiness vs. presence. There is one thing I disagree with pretty strongly though: his claim that variables should be declared where they make sense.

The author states in the article:

I declare a variable where it makes sense. Much of the time this is at the top of the scope, but there are enough exceptions to make me shake my head in dissapproval [sic] at the thought of a style guide imposing religious top-of-scope declarations.

Simply put I don't agree, and the reason is variable hoisting. While this is an easy enough concept for good JavaScript programmers, it causes constant confusion and heartache for programmers coming from other languages and programmers with less experience.

Let's look at a common bug that I come across far more often than my sanity and faith in other programmers would like:

var arr = [1, 2, 3, 4]  
for(var i = 0; i < arr.length; i++) {  
    var entry = arr[i];
    setTimeout(function() {
        console.log(entry);
    }, 100);
}

Most often this design pattern is used with event listeners, not setTimeout, but the end result is the same: developers are confused when their output is:

4  
4  
4  
4  

Rewriting this code with the var declarations at the top make it clear what's going on, and the bug would have (most likely) been avoided. Why?

It all comes down to variable hoisting (a term I disagree with because of some under the hood implementation details, but whatever). JavaScript runtimes evaluate code in two phases, not one. In the first pass, all identifiers (variables and functions) are determined and added to the current context's lexical environment (basically a symbol table in JavaScript that matches identifier names to their values). After this pass has been completed, the code is then executed in a second pass. In effect, JavaScript interpreters actually see the above code as:

var arr,  
    i,
    len,
    entry;
arr = [1, 2, 3, 4]  
for(i = 0; i < arr.length; i++) {  
    entry = arr[i];
    setTimeout(function() {
        console.log(entry);
    }, 100);
}

It becomes obvious here that entry is a single instance that is continually overwritten in the for loop as opposed to four separate instances, but it's not so obvious in the original version. My advice: always, without exception, declare your variables at the top of a function if in a function, else at the top of the file. In fact, this is the only design pattern that I do recommend following religiously in JavaScript. It's just too easy to get confused otherwise.

But what if you're a JavaScript expert who understands variable hoisting perfectly? You should still declare your variables at the top. I still follow this design pattern, despite the fact that I am intimately familiar with how JavaScript runtimes work since I'm writing one myself. The reason: no one ever works in a vacuum. Other people are bound to work on your code at some point in time. They may not be an expert like you or me, and they may end up breaking all of the amazing work you did on the project before they took it over. Also, as JavaScript experts, we should be trying to help out other devs who aren't experts, and "Do as I say, not as I do" doesn't exactly go over well.

We should be setting an example of how to write good code. Not just good according to our own standards, or good for ourselves, but good for everyone. Yes it's annoying declaring variables at the top, but it really does save time down the road when dealing with non-experts.

Update: So I no longer agree with what I wrote above, please disregard it :). My basic reasons why are summed up well by Angus Croll in his presentation "The Politics of JavaScript". These days, I usually either declare variables inline if they are initialized in one spot, or declare them at the innermost block that contains all initializations, e.g.:

function foo() {  
  console.log('start');
  for (var i = 0; i < 10; i++) {
    console.log(i);
  }
  var val;
  if (1) {
    val = true;
  } else {
    val = false
  }
}