A function is a container of logic that can be defined in one place and then executed any number of times somewhere else. While we do have classes in JavaScript, functions tend to be the preferred method of organizing code, creating interfaces, or simply making variables private. One of the reasons functions are so powerful in JavaScript is our ability to pass functions around like data and return functions from other functions, aka higher order functions. But before we jump to that, let’s ensure we are starting from the same mental model and vocabulary when we are discussing functions in JavaScript so that we can build from a strong foundation.
We define a function using the function keyword, a pair of parenthesis, and wrap the block of code in brackets like this:
/** Function keyword */
function() {
// does something
}
We call the example above an anonymous function because it doesn’t have a name. If we want to refer to a function later in our code, we need a way to reference it so we can give it a name a few different ways. Here are two common ways:
In order to do anything with the logic defined in our function, we need to do much more than just define a function — we also have to call it. Let’s say you invented a friendly toaster that says “Hello”. Manufacturing the toaster is like defining a function:
functionbraveToaster() {
return'Hello';
}
However, turning the toaster on to say “Hello” is like calling / invoking / executing the function. These are all words that mean the same thing: make the function run the code inside the two curly braces. Before the moment of invocation / call-time / execution, the code between the braces does not run and has never run. The JS engine effectively skips over any code inside the body of the function until the function is called.
functionbraveToaster() {
return'Hello';
}
braveToaster(); // --> 'Hello'
Code is executed from top to bottom so be sure to define your function before you invoke it or you may run into some issues.
Anatomy of a function
Function Body
Function Name
Arguments
Parameters
Invocation
Stacks: Call Stack, Stack Trace
The stack trace is a historical log of what functions have been called so far It essentially keeps track of where you are in a program as it executes. A stack trace gives an in-order list of all the functions executed up to the point where an error was thrown or your debugger was paused. We often see stack traces in error messages when we are debugging. But you can see the stack trace in your code at any given point by adding console.trace() to a line. Let’s try it out!
The stack trace will list the most recent functions called in order up until the error was thrown or the console.trace() was run. In addition to the function name, we often get the file name and line number which is often helpful when we are trying to track down a problem. You can use this to backtrack the functions that were executed up until that point. If the issue isn’t obvious when you are debugging an error, I recommend putting a debug statement in so you can walk through the code and inspect the various values and inputs for anything that seems unusual.
When you experience a stack overflow, this is when you have an infinite loop or missed the base case for your recursive call. It causes too many function calls to be stored in the call stack than it can handle. The error looks like this in the console and can crash your browser: