Jeff Lembeck learns a code or two

Serious code business!

JavaScript function name(param) vs. var name = function(param)

Bloated title for this, I know, and likely a subject that will return more Google hits than one can possible imagine, but what's another lesson in how JS works?

There are two well-known ways to write a function in JS:

function foo( param ){
  console.log( param );
}

and

var foo = function( param ){
  console.log( param );
};

For most situations, what you're dealing with here is all one and the same. After this code runs, you can call foo(2) and it will, in turn, call console.log( 2 ). Seems simple enough. But what if somebody calls the function before it is defined on the page? Seems like a prime spot for an error, right?

foo(2);
var foo = function( param ){
  console.log( param );
}

Go ahead and write that into a file and run it. The result should be: "TypeError: undefined is not a function." This makes some level of sense. Due to hoisting in JS, you are calling the equivalent code of:

var foo;
foo(2);
foo = function( param ){
  console.log( param );
};

Clearly, at this point, foo is undefined when it is called.

Now, let's try the other way:

foo(2);
function foo( param ){
  console.log( param );
}

You’d expect the same result, correct? Of course not. This actually will print “2” out to the console.

Why?

Because functions created in this manner are not just hoisted at the name level, but also at the implementation level, so writing code like that is actually read like this:

function foo(param){
  console.log( param );
}
foo(2);

despite how you wrote it.

Big deal, you say. Who cares if every function I write has its implementation hoisted?

Let’s look at another example.

var foo;
if( true ){
  foo = function(){
    console.log( "true" );
  };
} else {
  foo = function(){
    console.log( "false" );
  };
}
foo();

Well, while this example is contrived, the output should be “true”, and it is.

What about if we changed the way we write functions?

if( true ){
  function foo(){
    console.log( "true" );
  }
} else {
  function foo(){
    console.log( "false" );
  }
}
foo();

Any guess out the output? It’s “false.”

Due to the hoisting of implementation, for the level of scope in which these functions exist, the lowest foo defined on the page, no matter where it exists in the flow, will win out.

This can be absolutely damaging if you’re, say, creating a callback based upon info being passed. So, be careful out there when creating functions.

Back to Blog