Register to get access to free programming courses with interactive exercises

Higher-order functions JS: Functions

JavaScript has a built-in sort method that sorts an array. By default, this method sorts the array in a very convoluted way: it sets each element of the array to a string type and compares the resulting strings based on the order of the Unicode code points. Such sorting is suitable for simple situations, for example for numerical values, but stops working in the case of more complex comparisons, for example when each element of the array is an object.

Let's imagine the situation: a list of users comes into the program and needs to be sorted by age and displayed on the screen.

const users = [
  { name: 'John', age: 19 },
  { name: 'Richard', age: 1 },
  { name: 'Antony', age: 4 },
  { name: 'Alex', age: 16 },
];

The default sorting cannot properly sort such an array. And this applies to any kind of sorting we might need. We may want to sort by any parameter (or even by a set of parameters) and in any order. Sorts are needed often, and many of them are quite complex.

In languages where functions are not data (first-order objects), we would have to implement our own sort()function for each type of sorting. But there is a better way in JavaScript. Let's look at the definition of the built-in sort() method:

elements.sort([compareFunction])

It takes the optional compareFunction() parameter, a function that specifies how to sort the given array. The general idea is that we don't need to implement the sorting algorithm every time for every situation, because it doesn't change. All that changes are the elements that are compared to each other in the sorting process. And the sort() method delegates interaction with these elements to the called code:

const users = [
  { name: 'John', age: 19 },
  { name: 'Richard', age: 1 },
  { name: 'Antony', age: 4 },
  { name: 'Alex', age: 16 },
];

// The function takes the array elements to be compared as input
const compare = (a, b) => {
  if (a.age === b.age) {
    return 0;
  }

  return a.age > b.age ? 1 : -1;
};

users.sort(compare);

console.log(users);
// => [ { name: 'Richard', age: 1 },
//      { name: 'Antony', age: 4 },
//      { name: 'Alex', age: 16 },
//      { name: 'John', age: 19 } ]

https://repl.it/@hexlet/js-functions-high-order-functions-sort-en

The sort() method does all the work of directly moving the elements in the array. But which element is bigger or smaller is up to the programmer. Such a scheme is achieved by the very custom function that is passed when sort(). is called. This function takes two parameters as input - sort() gives it the two items it is currently comparing. In our case, the elements are users. Your task is to calculate within this function what is more or less and do the following: if the elements are equal, you have to return 0, if the first element is greater than the second one, they are considered to be unsorted and return 1, otherwise it returns -1, and sort() makes them sorted.

From the code, you can see that inside the function, the comparison is based on the age property of the passed users. It is not hard to guess that this function is called many times inside sort() (namely for each comparison). As soon as it starts returning -1 for each pair of elements, sorting is complete.

The sort() method belongs to the so-called higher order functions. Higher-order functions are functions that either accept or return other functions, or do all at once. Such functions usually implement some generalized algorithm (e.g., sorting), and delegate the key part of the logic to the programmer through a function. The main advantage of using such functions is the reduction of duplication.

The function that is passed inside the sort() method has its own name. Such functions are called callbacks. Any function that is not called directly by the programmer, but is called by some function to which we pass it, becomes a callback function.

In the example above, it is not necessary to create a constant for the function. Frankly, they are rarely written in constants at all. A typical use looks like a direct function-to-function transfer:

users.sort((a, b) => {
  if (a.age === b.age) {
    return 0;
  }
  return a.age > b.age ? 1 : -1;
});

// The same, but use Math.sign function
users.sort((a, b) => Math.sign(a.age - b.age));

Take some time to understand where one function ends and another begins. We will start using code like this in the next lesson.

What remains to be considered is how the challenge is going on inside. There will be nothing new in terms of syntax.

const say = (fn) => {
  const message = fn();
  console.log(message);
};
// or this way:
// const say = (fn) => console.log(fn());

const myCallbackFn = () => 'hi!';
say(myCallbackFn); // => hi!
// or this way:
// say(() => 'hi!');

The say() function makes a call to a function inside the fn()parameter. In this example, the function returns a string that is immediately displayed on the screen.

Higher-order functions are so convenient in most languages that they can almost entirely replace the use of loops. For example, the canonical JS code looks like this:

// Just demonstration
// There is no need to disassemble it
users
  .filter((user) => user.age >= 16)
  .map((user) => `${user.name} is ${user.age} years old`)
  .join('\n');
// => John is 19 years old
//    Alex is 16 years old

This code contains 2 higher-order functions (filter() and map()), 2 functions - arguments and two passes (this is what higher-order functions do) through the user list. The code is very expressive and concise.

In the following lessons, we will look at the three most important higher-order functions that can be used to solve almost any problem. Two of these are used in the example above, map() and filter(), and the third is — reduce(). They are all available in the standard JavaScript library.

Gradually, using these functions, we will completely abandon the use of loops. JavaScript is a language in which the logic of operation is based on higher-order functions. You have to get used to them and gradually incorporate them into your developer's arsenal. As of the next lesson, loops are no longer used in JavaScript courses. Look at the example of real code and notice the absence of loops. Soon you will learn to write it the same way.


Recommended materials

  1. Higher-order function

Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.bookmate">Bookmate</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.healthsamurai">Healthsamurai</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.dualboot">Dualboot</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.abbyy">Abbyy</span>
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions