- What Are Function Declarations?
- What Are Function Expressions?
- The Differences Between Function Expressions & Declarations
- How to Choose Between Expressions and Declarations
- Unlocking the Function Expression: JavaScript Hoisting Differences
- Conclusion
- Frequently Asked Questions (FAQs) about Function Expressions and Function Declarations
There are two ways to create functions in JavaScript: function expressions and function declarations. In this article, we will discuss when to use function expressions vs. function declarations, and explain the differences between them.
Function declarations have been used for a long time, but function expressions have been gradually taking over. Many developers aren’t sure when to use one or the other, so they end up using the wrong one.
There are a few key differences between function expressions and function declarations. Let’s take a closer look at those differences, and when to use function expressions vs. function declarations in your code.
function funcDeclaration() {
return 'A function declaration';
}
let funcExpression = function () {
return 'A function expression';
}
What Are Function Declarations?
Function declarations are when you create a function and give it a name. You declare the name of the function when you write the function keyword, followed by the function name. For example:
function myFunction() {
// do something
};
As you can see, the function name (myFunction
) is declared when the function is created. This means that you can call the function before it is defined.
Here is an example of a function declaration:
function add (a, b) {
return a + b;
};
What Are Function Expressions?
Function expressions are when you create a function and assign it to a variable. The function is anonymous, which means it doesn’t have a name. For example:
let myFunction = function() {
// do something
};
As you can see, the function is assigned to the myFunction
variable. This means that you must define the function before you can call it.
Here is an example of a function expression:
let add = function (a, b) {
return a + b;
};
The Differences Between Function Expressions & Declarations
There are a few key differences between function expressions and function declarations:
- Function declarations are hoisted, while function expressions are not. This means that you can call a function declaration before it is defined, but you cannot do this with a function expression.
- With function expressions, you can use a function immediately after it is defined. With function declarations, you have to wait until the entire script has been parsed.
- Function expressions can be used as an argument to another function, but function declarations cannot.
- Function expressions can be anonymous, while function declarations cannot.
Understanding Scope in Your Function Expression: JavaScript Hoisting Differences
Similar to the let
statement, function declarations are hoisted to the top of other code.
Function expressions aren’t hoisted. This allows them to retain a copy of the local variables from the scope where they were defined.
Normally, you can use function declarations and function expressions interchangeably. But there are times when function expressions result in easier-to-understand code without the need for a temporary function name.
How to Choose Between Expressions and Declarations
So, when should you use function expressions vs. function declarations?
The answer depends on your needs. If you need a more flexible function or one that is not hoisted, then a function expression is the way to go. If you need a more readable and understandable function, then use a function declaration.
As you’ve seen, the two syntaxes are similar. The most obvious difference is that function expressions are anonymous, while function declarations have a name.
Today, you would typically use a function declaration when you need to do something that function expressions cannot do. If you don’t need to do anything that can only be done with a function declaration, then it is generally best to use a function expression.
Use function declarations when you need to create a function that is recursive, or when you need to call the function before you define it. As a rule of thumb, use function expressions for cleaner code when you don’t need to do either of those things.
Benefits of function declarations
There are a few key benefits to using function declarations.
- It can make your code more readable. If you have a long function, giving it a name can help you keep track of what it’s doing.
- Function declarations are hoisted, which means that they are available before they are defined in your code. This helps if you need to use the function before it is defined.
Benefits of function expressions
Function expressions also have a few benefits.
- They are more flexible than function declarations. You can create function expressions and assign them to different variables, which can be helpful when you need to use the same function in different places.
- Function expressions are not hoisted, so you can’t use them before they are defined in your code. This helps if you want to make sure that a function is only used after it is defined.
When to choose a function declaration vs. function expression
In most cases, it’s easy to figure out which method of defining a function is best for your needs. These guidelines will help you make a quick decision in most situations.
Use a function declaration when:
- you need a more readable and understandable function (such as a long function, or one you’ll need to use in different places)
- an anonymous function won’t suit your needs
- you need to create a function that is recursive
- you need to call the function before it is defined
Use a function expression when:
- you need a more flexible function
- you need a function that isn’t hoisted
- the function should only used when it is defined
- the function is anonymous, or doesn’t need a name for later use
- you want to control when the function is executed, using techniques like immediately-invoked function expressions (IIFE)
- you want to pass the function as an argument to another function
That said, there are a number of cases where the flexibility of function expressions becomes a powerful asset.
Unlocking the Function Expression: JavaScript Hoisting Differences
There are several different ways that function expressions become more useful than function declarations.
- Closures
- Arguments to other functions
- Immediately Invoked Function Expressions (IIFE)
Creating Closures with Function Expressions
Closures are used when you want to give parameters to a function before that function is executed. A good example of how this can benefit you is when looping through a NodeList
.
A closure allows you to retain other information such as the index, in situations where that information isn’t available once the function is executed.
function tabsHandler(index) {
return function tabClickEvent(evt) {
// Do stuff with tab.
// The index variable can be accessed from within here.
};
}
let tabs = document.querySelectorAll('.tab'),
i;
for (i = 0; i < tabs.length; i += 1) {
tabs[i].onclick = tabsHandler(i);
}
The attached event handlers are executed at a later time (after the loop is finished), so a closure is needed to retain the appropriate value of the for
loop.
// Bad code, demonstrating why a closure is needed
let i;
for (i = 0; i < list.length; i += 1) {
document.querySelector('#item' + i).onclick = function doSomething(evt) {
// Do something with item i
// But, by the time this function executes, the value of i is always list.length
}
}
It’s easier to understand why the problem occurs by extracting the doSomething()
function out from within the for
loop.
// Bad code, demonstrating why a closure is needed
let list = document.querySelectorAll('.item'),
i,
doSomething = function (evt) {
// Do something with item i.
// But, by the time this function executes, the value of i is not what it was in the loop.
};
for (i = 0; i < list.length; i += 1) {
item[i].onclick = doSomething;
}
The solution here is to pass the index as a function argument to an outer function so that it can pass that value to an inner function. You’ll commonly see handler functions used to organize the information that an inner returning function needs.
// The following is good code, demonstrating the use of a closure
let list = ['item1', 'item2', 'item3'],
i,
doSomethingHandler = function (itemIndex) {
return function doSomething(evt) {
// now this doSomething function can retain knowledge of
// the index variable via the itemIndex parameter,
// along with other variables that may be available too.
console.log('Doing something with ' + list[itemIndex]);
};
};
for (i = 0; i < list.length; i += 1) {
list[i].onclick = doSomethingHandler(i);
}
Learn more about closures and their usage.
Passing Function Expressions as Arguments
Function expressions can be passed directly to functions without having to be assigned to an intermediate temporary variable.
You’ll most often see them in the form of an anonymous function. Here’s a familiar jQuery function expression example:
$(document).ready(function () {
console.log('An anonymous function');
});
A function expression is also used to handle the array items when using methods such as forEach()
.
They don’t have to be unnamed anonymous functions, either. It’s a good idea to name the function expression to help express what the function is supposed to do and to aid in debugging:
let productIds = ['12356', '13771', '15492'];
productIds.forEach(function showProduct(productId) {
...
});
Immediately Invoked Function Expressions (IIFE)
IIFEs help prevent your functions and variables from affecting the global scope.
All the properties within fall inside the anonymous function’s scope. This is a common design pattern that’s used to prevent your code from having unwanted or undesired side-effects elsewhere.
It’s also used as a module pattern to contain blocks of code in easy-to-maintain sections. We take a deeper look at these in Demystifying JavaScript closures, callbacks, and IIFEs.
Here’s a simple example of an IIFE:
(function () {
// code in here
}());
… which when used as a module, can result in some easy-to-achieve maintainability for your code.
let myModule = (function () {
let privateMethod = function () {
console.log('A private method');
},
someMethod = function () {
console.log('A public method');
},
anotherMethod = function () {
console.log('Another public method');
};
return {
someMethod: someMethod,
anotherMethod: anotherMethod
};
}());
Conclusion
As we’ve seen, function expressions aren’t radically different from function declarations, but they can often result in cleaner and more readable code.
Their widespread use makes them an essential part of every developer’s toolbox. Do you use function expressions in your code in any interesting ways that I haven’t mentioned above? Comment and let me know!
Frequently Asked Questions (FAQs) about Function Expressions and Function Declarations
What is the main difference between function expressions and function declarations?
The primary difference between function expressions and function declarations lies in the way JavaScript engine interprets them. A function declaration is parsed before any code is executed, meaning you can call a function that is declared later in your code. This is known as function hoisting. On the other hand, function expressions are not hoisted, and therefore cannot be invoked before they are defined.
Can you provide an example of a function declaration and a function expression?
Sure, here’s an example of each:
Function Declaration:function greet() {
console.log('Hello, world!');
}
Function Expression:var greet = function() {
console.log('Hello, world!');
};
When should I use a function declaration over a function expression?
Function declarations are generally used when you need to create a function that will be used throughout your code, as they are hoisted to the top of the scope. This means you can call the function before it is declared in your code. Function expressions, on the other hand, are typically used when a function needs to be used once or a limited number of times, or when a function is to be passed as an argument to another function.
Can function expressions be named?
Yes, function expressions can be named. This can be useful for debugging, as the function’s name will appear in the stack trace. Here’s an example:var greet = function greeting() {
console.log('Hello, world!');
};
What is a function hoisting?
Function hoisting in JavaScript is a behavior in which function declarations are moved to the top of their containing scope during the compile phase, before the code has been executed. This means that you can call a function before it has been declared in your code. However, it’s important to note that function expressions, even those assigned to variables, are not hoisted.
What is an Immediately Invoked Function Expression (IIFE)?
An Immediately Invoked Function Expression (IIFE) is a function expression that is executed as soon as it is defined. The syntax for an IIFE looks like this:(function() {
console.log('Hello, world!');
})();
Can I use function expressions and function declarations interchangeably?
While function expressions and function declarations can often be used interchangeably, there are some key differences to keep in mind. Function declarations are hoisted, meaning they can be called before they are declared. Function expressions, on the other hand, are not hoisted, so they cannot be invoked before they are defined. Additionally, function expressions can be anonymous or named, while function declarations must always be named.
What is the advantage of using a function expression?
Function expressions offer several advantages. They can be anonymous, they can be made to be self-executing (Immediately Invoked Function Expression), and they can be assigned to variables and passed around. This makes function expressions ideal for use as closures and callback functions.
Are there any performance differences between function expressions and function declarations?
In general, the performance difference between function expressions and function declarations is negligible and is unlikely to impact the performance of your JavaScript code. The choice between function expressions and function declarations should be based on your specific use case and coding style preference.
Can a function expression be used as a closure?
Yes, function expressions are often used to create closures in JavaScript. A closure is a function that has access to its own scope, the outer function’s scope, and the global scope. Here’s an example of a closure created using a function expression:var add = (function () {
var counter = 0;
return function () {counter += 1; return counter}
})();
add();
add();
add();
// the counter is now 3
I'm a web developer living in Christchurch (thanks for all the quakes) where JavaScript is my forte. When off the computer I volunteer down at the local community centre, or enjoy playing tabletop games such as Carcassonne or Stone Age with friends.