What's the Difference Between JavaScript Function Statement and Function Expression?

Both, function expression and function statement/declaration, can be used to create a function:

// function declaration/statement
function stmt() {
    // ...
}
// function expression
const expr = function () {
    // ...
};

The main differences between the two are in terms of the following:

Hoisting

Function statements are hoisted to the top of the enclosing function or global scope. This means that you can call the function before it is declared:

hoisted(); // 'foo'

function hoisted() {
    console.log('foo');
}

Same is not true with function expressions, as they are not hoisted. This is true, regardless of whether you use var, const or let to create a function expression. Consider, for example, the following:

// ReferenceError: notHoisted is not defined
notHoisted();

const notHoisted = function() {
    console.log('foo');
};
// ReferenceError: notHoisted is not defined
notHoisted();

let notHoisted = function() {
    console.log('foo');
};
// TypeError: notHoisted is not a function
notHoisted();

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

Mutability

Function statements can be overridden (and are, therefore, mutable):

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

foo(); // 'bar'

function foo() {
    console.log('bar');
}

Function expressions declared as a let or const cannot be redeclared within the local scope:

const foo = function() {
    console.log('foo');
}

// SyntaxError: Identifier 'foo' has already been declared
const foo = function() {
    console.log('bar');
}
let foo = function() {
    console.log('foo');
}

// SyntaxError: Identifier 'foo' has already been declared
let foo = function() {
    console.log('bar');
}
const foo = function() {
    console.log('foo');
}

// SyntaxError: Identifier 'foo' has already been declared
var foo = function() {
    console.log('bar');
}

Naming

Function name is required in a function statement/declaration; it has the following syntax:

function name([param1, ..., paramN]) {
   [statements]
}

For example:

function foo() {
    // ...
}

On the other hand, function name is optional in a function expression, which has the following syntax:

function [name]([param1, ..., paramN]]) {
  statements
}

For example:

// unnamed function expression
const foo = function() {
    // ...
};
// named function expression
const foo = function bar() {
    console.log(123);
};

console.log(foo.name); // 'bar'
console.log(foo()); // 123
console.log(typeof bar); // undefined

This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.