If you didn’t know already, JavaScript functions are first-class objects. They can be treated like any other JavaScript Object data type. Functions can be referenced by variables, declared with literals, and even passed as function parameters.
Functions serve an important role in JavaScript because they are the primary modular units of execution. If we want to write clean code that does not pollute the global namespace we would most probably write our logic inside functional blocks of code.
Now, this is made easy in JavaScript because JavaScript treats functions almost the same as any regular object. We mentioned this above but we can pass functions as arguments to other functions, we can assign functions to variables, array entries, and properties of other objects, we can return functions as results from other functions and we can add dynamical properties to functions.
Here are some examples:
// literal function creation function literalFunction() {} // assigning a function to a variable let sum = function() {}; //adding function to an array listOfPeople.push(function() {}); // assign function as property of an object people.age = function() {} //passed as an argument to a function function calculateAge(functionArg) { functionArg(); } calculateAge(function() {}) // returned from function function returnFunction() { return function() {} } // adding a new property to a function let functionRabbits = function() {} functionRabbits.name = "Buggs Bunny";
JS frameworks and libraries use lots of these special properties.
In React, for example, you would often get functions as return values from other functions, and in Angular functions are the main building blocks of components. Even the lifecycle methods are special forms of functions!
There is one thing though, that functions can do and other JavaScript objects can’t. Functions are invokable. We can execute functions in order to perform the contents of that function.
Functional programming
We can easily explain functional programming as a style of programming that is focused on solving problems by chaining or composing functions together. In imperative languages, functions are mostly written in a series of sequential steps, but in functional programming, we can ‘join’ them together to produce results.
Functions being first-class objects in JavaScript introduces the language to functional paradigms. One characteristic of first-class objects is that we can pass them to functions. Functions being first-class objects themselves means that we can pass them to other functions. Thus we came across an interesting concept called callback functions.
Callback functions
A callback function is a special type of function that is set up to be invoked at a later time. The name is related to the functionality – meaning that the code will later “call back” the function into execution. We use callbacks often either for event listeners on our DOM or API calls.
Below we’ve written a simple callback function example. Functionally it is quite useless but it shows how a function can accept a reference to another one as a parameter and invoke that function as a callback.
function callBackFunction() { console.log("This is a callback function."); return 2 + 2; } function caller(callbackArg) { let sum = callbackArg(); return sum; } console.log(caller(callBackFunction));
So how does this work? Our caller
method accepts a function as a parameter. Inside the caller
method we actually invoked the callbackArg
method which displays a text to the screen and returns the sum
of numbers 2 and 2. The caller method will store this return value into the variable sum
and it will return this variable.
So in the last line of code we actually print out that sum
variable of 4, which we retrieved all the way from the callbackFunction
.
We are showing a more real-life example in the listing below:
myPics.addEventListener('mousemove', e => { if (isDrawing === true) { drawLine(context, x, y, e.offsetX, e.offsetY); x = e.offsetX; y = e.offsetY; } });
This block of code is picked off the Mozilla Documentation, and it checks for a 'mousemove'
event, in which case it will run the contents of the method. Another interesting thing here – we didn’t declare our callback outside, but instead, we wrote the contents of the function directly inside the round brackets. This is also allowed, and can be because we don’t need to create extra declarations.
Because they are easily referenced, callbacks are easy to understand. They don’t pollute the global namespace with unnecessary functional declarations, especially if we would use those declarations only once.
Final Words
Hope you had fun learning about JavaScript functions and their first-class properties.
For more articles please click below, or check the blog.
- Largest Palindrome Product
- Largest Prime Factor
- Even Fibonacci Numbers
- Multiples of 3 or 5
- How to find the missing number in a given integer array of 1 to 100?
- Understanding Javascript prototypes
- Difference between Promise.all() and Promise.race()
- JavaScript generators
- Using this and arguments
- Arrow functions in JavaScript