Все три термина связаны и идут вместе. Они так же просты для понимания, как и широко используются в javascript. И все они являются частью парадигмы функционального программирования javascript.

Вот краткое определение каждого типа функции, за которым следуют полные объяснения каждого из них.

Функция первого класса - это функция, которая была создана с целью передачи другим функциям. Он выполняет одну конкретную задачу, не имеет побочных эффектов и не предназначен для прямого вызова, а скорее для использования «другими функциями».

Те «другие функции», которые принимают одну из этих «функций первого класса» в качестве аргумента, называются функциями более высокого порядка. Функции высшего порядка также могут быть функциями, возвращающими функцию.

В функции более высокого порядка, когда один из переданных параметров является функцией, эта функция является функцией обратного вызова, поскольку она будет вызываться и использоваться в функции более высокого порядка.

Функция более высокого порядка названа так потому, что при использовании обратного вызова для выполнения операции внутри себя функция имеет «более высокую» цель, чем обычная функция. Когда он возвращает функцию, он также имеет «высшую» цель.

Функции первого класса

Функции первого класса должны создаваться выражениями функций, а не объявлениями функций. Благодаря этому их легко читать и передавать. Вот пример, который никогда не будет использоваться в реальном мире, но он должен показать эту концепцию более подробно ...

var add = (x, y) => x + y;
var subtract = (x, y) => x - y;
var multiply = (x, y) => x * y;
function numbers(fn, x, y){
  return fn(x, y);
}
var addResult = numbers(add, 3, 2);
var subtractResult = numbers(subtract, 3, 2);
var multiplyResult = numbers(multiply, 3, 2);

Вышеупомянутая функция чисел - это функция более высокого порядка, которая принимает функцию первого класса в качестве своей функции обратного вызова. Он построен на заказ (не встроен в js.)

Функции высшего порядка

Обычно, когда новички изучают функции высшего порядка, они изучают функции Array.prototype, которые теперь предоставляет javascript как часть языка. Это .map (), .filter (), .every (), .some () и многие другие, которые работают, принимая функцию в качестве параметра и применяя ее к каждому элементу массива.

.map ()

Функция .map () - это функция более высокого порядка, которая выполняет обратный вызов для каждого элемента в массиве и помещает каждый результат в новый массив.

var nums = [1, 2, 3, 4, 5];
var numsTimesTwo = nums.map(num => num * 2);
// numsTimesTwo = [2, 4, 6, 8, 10];

В приведенном выше примере в качестве обратного вызова используется анонимная функция. Однако вы также можете сделать то же самое, создав и используя функцию первого класса.

var nums = [1, 2, 3, 4, 5];
var multiplyByTwo = num => num * 2;
var numsTimesTwo = nums.map(multiplyByTwo);
// nums.map(multiplyByTwo) 
// would be exactly the same as
// nums.map(num => num * 2)

.фильтр()

Функция .filter () запускает функцию обратного вызова для каждого элемента в массиве и возвращает значение true или false для каждого элемента. Если это правда, он отправит элемент в новый массив.

var nums = [1, 2, 3, 4, 5];
var oddNumbers = nums.filter(num => num % 2 !== 0 );
// oddNumbers = [1, 3, 5];

И сделано с помощью первоклассной функции в качестве обратного вызова…

var nums = [1, 2, 3, 4, 5];
var isOdd = num => num % 2 !== 0;
var oddNumbers = nums.filter(isOdd);

Парадигма функционального программирования

Вы можете спросить, зачем вообще создавать функцию первого класса, почему бы просто не закодировать анонимную функцию в качестве обратного вызова, в конце концов, это так просто?

Вот причина ... Потому что цель функционального программирования и кодирования в целом - написание кода многократного использования. Не повторяйся!

Итак, в приведенном выше примере для .filter () мы написали функцию первого класса isOdd. Теперь мы можем использовать isOdd в любой другой функции всей программы. Давайте продолжим работу с другими функциями более высокого порядка, но теперь мы воспользуемся функцией isOdd.

.каждый()

Функция .every () будет запускать функцию обратного вызова для каждого элемента в массиве, проверяя возвращаемое значение true или false. Если каждый элемент в массиве возвращает истину, он вернет истину. Если какой-либо элемент в массиве вернет false, он остановит свой цикл и немедленно вернет false.

var nums = [1, 2, 3, 4, 5];
if( nums.every(isOdd) ){
  console.log('Yes, they are all odd!');
} else {
  console.log('Nope, they are not all odd!');
}

.некоторые()

Функция .some () будет запускать функцию обратного вызова для каждого элемента в массиве, проверяя возвращаемое значение true или false. Если какой-либо элемент в массиве вернет истину, он вернет истину. Если все элементы в массиве вернут false, он вернет false. Как только он получит одно истинное значение, он остановит цикл и вернет истину.

var nums = [1, 2, 3, 4, 5];
if( nums.some(isOdd) ){
  console.log('At least one of these numbers are odd!');
} else {
  console.log('None of these numbers are odd!');
}

В следующих статьях мы еще глубже погрузимся в то, как фреймворки и библиотеки Javascript используют функции первого класса, функции высшего порядка и функции обратного вызова для создания удивительно полезных инструментов для разработчиков. Мы также погрузимся в то, что буквально происходит за кулисами этих функций.