There’s no need to declare all javascript vars once at the top of a function, and there hasn’t been for a while.

Back in the bad old days of javascript, people suddenly started writing all of their code like this:

The rule here is:

  • Only one var statement per function
  • That var statement must be at the top of the function

This style gained a lot of popularity after Douglas Crockford’s JavaScript: The Good Parts:

JavaScript has C syntax, but its blocks don’t have scope. So, the convention that variables should be declared at their first use is really bad advice in JavaScript. JavaScript has function scope, but not block scope, so I declare all of my variables at the beginning of each function. JavaScript allows variables to be declared after they are used. That feels like a mistake to me, and I don’t want to write programs that look like mistakes.

And to this day jslint, Crockford’s linting tool, errors out by default if you don’t follow this rule:

But, why?

The reason is, as Crockford mentions: JavaScript allows variables to be declared after they are used. Dubbed “variable hoisting”, this has the potential to create subtle and dangerous bugs:

This code deceptively outputs “10”, because var total has the effect of hoisting and declaring total as undefined at the top of the function, causing it to fail the truthiness check on line 8.

But is Crockford’s rule really necessary any more? The answer is no, not really.

Using ES2015/ES6, either in node or through babel, we can just write our code to use let instead of var, which gives our variables block scope, and does not hoist them.

This entirely sidesteps the problem, and means there’s no incentive any more to define multiple variables per let statement, or to group all of their variable definitions at the top of a function — although for some reason you still see people doing this, even with let.

But what about my existing javascript, that I haven’t converted to ES2015 yet?

Eslint catches variable hoisting kinds of bugs a mile off (with its default configuration), by throwing an error if:

With these two simple rules, I’d challenge anyone to come up with a bug caused by variable hoisting, even if you continue to use var.

And if you are using ES2015 or up, I’d even recommend using eslint to prevent the use of var entirely and forcing let.

Even jslint will complain if you use a variable out of scope, or redeclare a variable from the outer scope:

Given this, it’s a mystery to me why jslint still enforces the single-var rule by default. At the very least, there’s a multivar option you can use to disable that rule.

In conclusion: please, please stop writing code with a bunch of variables declared in a single statement at the top of your function. It’s harder to maintain, reads less clearly, and in my mind has more potential to create bugs than preventing the problem it’s trying to solve. Like, for example, the risk of accidentally creating global variables if you forget to add some new variable to your single var statement, if you aren’t already using a linter.

Obviously, always use a linter (be safe, kids), because linters, even Crockford’s, invalidate the need to do single vars and catch variable hoisting before it happens. But if you don’t, or can’t, instead of following the single-var convention, follow these rules instead and you’ll have a much better time:

  • Never redeclare a var from a parent scope, or use the same name twice
  • Never reference a local variable before it is declared

Now you can learn to spot variable hoisting issues before they happen, rather than just blindly following an obscure single-var convention.

Thanks!

works for PayPal, as a lead engineer in Checkout. Opinions expressed herein belong to him and not his employer. daniel@bluesuncorp.co.uk

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store