JavaScript Functions – Declaration and Expression

This post is work-in-progress learning-note and still in active development and updated regularly.

In my another post, Understanding JavaScript Functions – The Basics,  common ways of defining a function, their basic syntax and some examples were discussed. In this post, I will focus on difference between the function declaration & function expression with some examples.

Function Declaration & Function Expression Overview
Basic Syntax: Function Declaration
//initialize function greeting (1) with single parameter
function greeting(name) { 
  console.log(`Hello ${name}, How are you?`);
}

//Invoke function Greeting (2) with 'Robert' as argument
greeting('Robert');

//OUTPUT (3)
Hello Robert, How are you?

Some key features of function declaration:

  • Start with function keyword
  • function definition should have a functionName followed by parentheses: ( )
  • Blocks of code to be executed are placed inside curly braces: { }
  • Declared functions are always stand-alone (can’t be part of non-functional blocks).
Basic syntax: function expression

Lets write the above greeting() function in function expression syntax, which looks like as follows:

//initialize function greeting (1) with single parameter
let greeting = function (name) { 
  console.log(`Hello ${name}, you are welcome!`);
}

//invoke greeting function (2) with 'Robert' argument
greeting('Robert');

//OUTPUT (3)
Hello Robert, you are welcome!

Some key features of function expression:

  • Does not start with function keyword
  • Function created inside an expression or another syntax construct (i.e. code can be part of non-functional code blocks)
  • In the following example, the function is created at the right side of the assignment expression = (typically function is assigned to a variable)
  • Function can be created with or without functionName (anonymous)
  • After close curly braces  } there is semicolon ;

Although, in both the function declaration and function expression, function is invoked in similar way greeting('Robert'); however when JS engine reads, they are read differently. That is what we will explored next!

Difference Between Function Declaration &  Expression
1. Function Declaration are Hoisted
//Invoke greeting function (1) with 'Robert' as argument
greeting('Robert');

//initialize function greeting (2) with parameter
function greeting (name) { 
  console.log(`Hello ${name}, you are welcome!`);
}

//OUTPUT
Hello Robert, you are welcome!

In the above example, greeting( ‘Robert’ ) function was invoked (1) before it was declared (2). To quote from The Modern JavaScript Tutorial: “when JavaScript prepares to run the script or a code block, it first looks for Function Declarations in it and creates the functions. We can think of it as an “initialization stage”. And after all of the Function Declarations are processed, the execution goes on. As a result, a function declared as a Function Declaration can be called earlier than it is defined.”

Tip: A Function Declaration is usable in the whole script/code block – The Modern JavaScript tutorial.

2. Function Expression are NOT Hoisted

To quote again from The Modern JavaScript Tutorial: “Function Expression is created when the execution reaches it and is usable from then on. Once the execution flow passes to the right side of the assignment let greeting = function (name) – the function is created and can be used (assigned, called etc) from now on.

//Invoke greeting function (1) with 'Robert' argument
greeting('Robert');

//initialize function greeting (2) with one parameter
let greeting = function (name) { 
  console.log(`Hello ${name}, you are welcome!`);
}

//OUTPUT (error with following message)
//Chrome
greeting is not defined  
//Firefox
can not access lexical declaration `greeting' before initialization 

Lets look at the above function and walk through how JS engine executes these codes. Misa Ogura explains this process very clearly in her post. First, JS engine encounters the let or var keyword and expects variable declaration follow and hoist the variable with a value of: undefined. It does not hoist the variable initiation. Now, Misa’s explanation start making sense:

  • When the JS engine encountered the variable declaration let greeting (name) in (2), it was hoisted as variable hoisting with a value: undefined.
  • The variable initialization (i.e. = function (name) { console.log(`Hello ${name}, you are welcome!`); } was not hoisted.
  • When the execution reached line (1) and tried to invoke greeting('Robert') it failed because undefined (hoisted value) is not a function.
  • When the function greeting('Robert') was called in (3) (see above previous section) only after assignment of greeting (name) to function expression in line (2), greeting('Robert') was successfully invoke.

Tip: A Function Expression is created when the execution reaches it and is usable from then on- The Modern JavaScript tutorial.

Conditionally Created Functions

This process can be confusing. To quote Dmitri Pavlutin from his postsome JavaScript environments can throw a reference error when invoking a function whose declaration appears within blocks {…} of if, for or while statements.  Let’s enable the strict mode and see what happens when a function is declared in a conditional:

// Example from Dmitri Pavlutn
'use strict';
  if (true) {
    function ok() {
      return 'true ok';
    }
  } else {
    function ok() {
      return 'false ok';
    }
  }
  console.log(typeof ok === 'undefined'); // => true
  console.log(ok()); // Throws "ReferenceError: ok is not defined"

In the above Dmitri’s example, function declaration was made inside a conditional block, therefore when ok() was called JS throws “ReferenceError: ok is not defined” error. It becomes even more confusing, if we use the same code under ‘non-strict‘ mode then it works and does not through error as shown below:

//Testted under NON-STRICT mode
if (true) {
    ok = function() {
      return 'true ok';
    };
  } else {
    ok = function() {
      return 'false ok';
    };
  }
  console.log(typeof ok === 'function'); // => true
  console.log(ok()); // => 'true ok'

Again quoting from Dmitri’s post “as a general rule for these situations, when a function should be create based on some conditions – use a function expression. Let’s see how it is possible:

//Example from Dmitri Pavlutin
'use strict';
  let ok;
  if (true) {
    ok = function() {
      return 'true ok';
    };
  } else {
    ok = function() {
      return 'false ok';
    };
  }
  console.log(typeof ok === 'function'); // => true
  console.log(ok()); // => 'true ok'

Because the function is a regular object, it is fine to assign it to a variable depending on a condition (Dmitri). Invoking ok() works fine and does not throw any errors.

Tip: MDN function declaration reference suggests avoiding function declaration in conditionals in production because of inconsistent results. For conditional function creation, use function expressions instead.

Benefits of Using Function expression
  • Because function expression are not hoisted,
  • Because they are also anonymous function, they can used as closures, or arguments to other function.
  • They are also preferred because they are considered to more cleaner & readable codes.
  • They are preferred in conditional use, as shown in examples above.
Resources & Further Reading:

While preparing this post, I have referred the following references extensively. Please to refer original posts for more detailed information.