In programming, a first-class function is when a function is treated as a variable. This is special because it means that a function can be passed into another function as an argument.

Not all languages support a first-class function idea, and these are usually natively imperative languages like C. Java and C++ also didn’t use to support first-class based ideas.

Imperative programming tells a computer how to do something — it’s a set of linear instructions that are executed in order. Declarative programming follows a generalized what should happen sequence. The control flow in a declarative language is not as strict and code can be executed asynchronously when required.

JavaScript is declarative by design and nature. The order of execution isn’t as vital towards arriving at the desired end-state for declarative programming.

Why is this important?

When it comes to first-class functions, you can assign a function to a variable but the actual value of the variable will not be set until it gets called. It’s a fuzzy area because the assignment does not happen instantly. Imperative programming requires clarity and first-class functions introduces a level of uncertainty.

Take a look at the following JavaScript code:

let catName = function(){ 
    return "Tibbers"; 
 }

In JavaScript, functions are not invoked until they are called. The above code is valid but catName is not set until it is called. The invocation will execute the function attached to it and assign catName with the value Tibbers.

When you assign a function directly to a variable, it’s called an anonymous function and you can call the variable by adding a pair of parentheses at the end. So to invoke (and therefore assign) the above variable, you’ll need to write catName()

To use a function as an argument, you need to pass in the function name.

For example:

let catName = function(){ 
    return "Tibbers"; 
 }
 
 function greet(name){
     console.log("hello " + name);
 }
 
 greet(catName());

catName is passed in as an argument for the greet() function. If you use catName without the parenthesis () , JavaScript will pass the contents of the function rather than execute it. This allows the function to be treated as a value.

The flow of execution looks something like this:

With first-class functions, you can also have a function return another function. This is called a higher-order function.

In JavaScript code, it can look something like this:

function calculateCart() {
     //do something here
     return cartTotal();
 }

This is valid JavaScript code because a function returned is treated as a value. You can also write the same thing using a variable.

const calculateCart = function(){
     //do something here
     return cartTotal();
 }

Why is the above set to const and not let or var? const ensures that the structure of the function cannot be changed later down the track, making it immutable by default. In JavaScript, immutability refers to the inability to change the values assigned. In the above example, a function is assigned as an immutable thing, which means that the process cannot be changed but the values being processed and passing through it can.

The return can also be in the form of an anonymous function. For example:

const calculateCart = function(){
     //do something here
     return function(){
         //do something here
     }
 }
 
 let myCart = calculateCart();
 myCart();

When you have higher-order functions, you need to invoke each level manually. If you don’t do this, it will return the function itself rather than the final expected return.

Why is this? Because functions are not executed unless they are called. This call has to be explicit.

That’s why for calculateCart to work properly, you need to assign it to another value first before invoking the chain.

Here’s what the execution chain looks like in a diagram:

Alternatively, you can also execute the nested function through double parenthesis.

const calculateCart = function(){
         //do something here
     return function(){
         //do something here
     }
 }
 
 calculateCart()();

Or if you’ve got more than two nested levels, you just need to add the same amount of parenthesis to ensure that the inner functions get invoked.

const calculateCart = function(){
         //do something here
     return function(){
         //do something here
         return function(){
           //do something here
         }
     }
 }
 
 calculateCart()()();

That’s basically first-class functions in a nutshell for JavaScript.

Share this post