JavaScript – Where to Declare Variables and Define Functions in JavaScript

coding-stylejavascriptscope

I'm reading the book JavaScript: The Good Parts.

On page 113 it recommends function expressions instead of function statements, because statements are subject to hoisting:

The statement:

function foo( ) {}

means about the same thing as:

var foo = function foo( ) {};

Throughout this book, I have been using the second form because it
makes it clear that foo is a variable containing a function value.

Further JSHint warns against function statements defined in a block, e.g. (my example):

if (foo) {
    function baz() {}
}

… e.g. because support for this isn't consistent between javascript engines; it produces the following error message:

Function declarations should not be placed in blocks. Use a function expression or move the statement to the top of the outer function.

A recommended work-around is a function expression, e.g. (my example):

if (foo) {
    baz = function() {}
}

My question is, where do I declare the baz variable?

The end of page 36 (the Scope section of the Functions chapter) says,

In many modern languages, it is recommended that variables be declared as late as
possible, at the first point of use. That turns out to be bad advice for JavaScript
because it lacks block scope. So instead, it is best to declare all of the variables used
in a function at the top of the function body.

Does that mean that it's best to declare the baz variable at the top of the function?

For example, like this:

function(foo) {
    // declare variables
    var baz;
    // implementation
    if (foo) {
        baz = function() {}
    }
}

Is this a best practice, or am I misunderstanding something, reading too much into it? I fear it makes it harder to maintain: because it separates the declaration of baz (i.e. var baz;) from its initialization. If I rename or delete one but not the other then suddenly the variable would exist at global scope.

Isn't it safer to code as follows, where var is used where the variable is first used?

function(foo) {
    // implementation
    if (foo) {
        var baz = function() {}
    }
}

I understand that the latter is functionality equivalent to the former. Is the latter contrary to a best-practice coding-style for Javascript?

Best Answer

My question is, where do I declare the baz variable?

So the generic answer to this question is "wherever you want", but of course that's not helpful and has pitfalls, so I'm going to tell you where I recommend putting it, and attempt to defend my logic as best as possible.


No matter where you declare a function* or variable** in JavaScript, the function or variable will be hoisted to the top of its containing scope***. If there is no containing scope, it will be implicitly added to the global namespace (in browsers this is window, in NodeJS this is global).

When a variable or function is hoisted, it means that the JavaScript interpreter will pretend as though your variable declaration were written as the first line of the containing scope.

In practice what this means is that when you write:

(function () {
  ...a...
  if (...b...) {
    var example = ...c...;
//  ^^^^^^^^^^^
  }
}());

It's actually evaluated as:

(function () {
  var example;
//^^^^^^^^^^^
  ...a...
  if (...b...) {
    example = ...c...;
  }
}());

* I'm referring to function declaration here. I.E. function name(...) {...}
** I'm referring to variable declaration with var here. I.E. var name
*** Containing scope is typically the wrapping function, but sometimes for various reasons there is no wrapping function.


Isn't it safer to code as follows, where var is used where the variable is first used?

Because of hoisting this classic best practice becomes susceptible to simple mistakes.

Consider the case where you write some code...

(function () {
  for (var i = 0; i < x.length; i++) {
    ...do stuff...
    if (...something happens...) {
      break;
    }
  }
  ...more stuff...
  ...even more stuff...
  doSomethingWith(i);
}());

Then you come back later, and need to add some new functionality, so you add:

...more stuff...
for (var i = 0; i < y.length; i++) {
  ...do stuff...
}
...even more stuff...

Now, if you combine the two it's easy to see in this contrived example that sloppiness has led to accidentally redeclaring and overriding the i variable.

This might seem silly, but it happens all the time. It's quite easy if you don't actively take steps to avoid it. This sort of an issue isn't a problem in languages with block scope, because i would be contained in each for loop's scope, and to use doSomethingWith, we would have had to expose the value of i to the parent scope.


With that all said, your question is really one of best practices. This is inherently subjective and will lead to disagreement. I'm going to post my opinion and I will attempt to defend it, but it should be treated as an opinion and not dogma.

In my opinion, functions should have the following flow:

  1. Directives
  2. Variable declaration
  3. Function declaration
  4. Variable instantiation
  5. Other code

(1) Directives are things like "use strict". They come first by definition.

(2) Variable declaration using var comes second. They could come after function declaration, or even in between, but I've found it makes them harder to find. I also recommend using exactly one var statement with each var placed on separate lines, organized alphabetically. This forces variables to be clustered together, and alphabetical ordering prevents accidental duplication.

(3) Function declaration comes next because functions are hoisted just like variables. Seeing what local APIs are available within a given scope is something I find useful.

(4) Variable instantiation comes after function declaration, and in my opinion should be separate from declaration. Yes there are circumstances where it's easier to just put them on the same line, but as a general rule, you can't go wrong with keeping them separate.

The reasoning for this one is two-fold.

First, the declaration will be interpreted to happen before the assignment, so writing code that reads the way the interpreter is going to interpret it will help with understanding.

Second, if the assignment is merged with the declaration, order suddenly starts to matter, and you lose the ability to consistently alphabetize your variables.

As an example:

(function () {
  var x = ...x...,
      y = ...y...,
      length = Math.sqrt(x * x + y * y);
//    ^^^^^^ no longer alphabetical
}());

If you separate the declaration from assignment, you can get the benefits of both:

(function () {
  var length,
      x,
      y;

  x = ...x...;
  y = ...y...;
  length = Math.sqrt(x * x + y * y);
}());

(5) Once you're done with all the setup for a function, you'll need to write the rest of the code. This step is the "rest of the code" step.


If you've been paying attention to ECMAScript2015, then you should know that there are two new ways to declare variables: let and const.

These new variable declarations use block scope. If you're assigning a variable that will never be overwritten, use const, otherwise use let.

Going back to:

Isn't it safer to code as follows, where var is used where the variable is first used?

let allows you to do this. If you can use let, stop using var; use let and const where the variables are first used; combine declaration with assignment:

ES5 way:

(function () {
  var example;
  ...
  example = ...;
}());

ES2015 way:

(function () {
  ...
  let example = ...;
}());
Related Topic