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

Сколько из вас когда-либо использовали функции высшего порядка?

Для большинства из вас, ребята, которые долгое время работали над JavaScript или библиотекой, такой как React.

Ответ будет таким: Много / почти каждый день и продолжайте добавлять к этому, например: .map(), .reduce(), .filter() и .forEach() . Но что, если я спрошу вас, сколько из вас создали свою функцию высшего порядка? Тогда я получу на 50% меньше негативных отзывов, чем в первый раз.

Итак, давайте теперь начнем и напишем нашу собственную первую функцию высшего порядка.

Функция высшего порядка — это функция, которая получает функцию в качестве аргумента или возвращает функцию в качестве вывода.

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

Допустим, у нас есть массив, который включает длину и высоту всех прямоугольников.

const rectangles = [{length: 10,height: 4},{length: 12,height: 6},{
length: 13,height: 3},{length: 8,height: 3}];

Теперь нам нужно вычислить площадь каждого прямоугольника и вывести только массив. Итак, большинство из нас сделает что-то вроде этого:

const area = rectangles.map((rectangle) => {
  return rectangle.length * rectangle.height;
});
console.log(area); // [ 40, 72, 39, 24 ];

Теперь давайте посмотрим, как мы можем сделать нашу карту похожей на функцию высшего порядка:

const rectangles = [{length: 10,height: 4},{length: 12,height: 6},{
length: 13,height: 3},{length: 8,height: 3}];
const area = function(rectangles){
  const output = [];
  for (let i = 0; i < rectangles.length; i++) {
    output.push(rectangles[i].length * rectangles[i].height);
  }
  return output;
};
console.log(area(rectangles)); // [ 40, 72, 39, 24 ]
const perimeter = function(rectangles){
  const output = [];
  for (let i = 0; i < rectangles.length; i++) {
    output.push(2 * (rectangles[i].length + rectangles[i].height));
  }
  return output;
};
console.log(perimeter(rectangles)); // [ 28, 36, 32, 22 ]

В приведенном выше коде мы создали две функции для вычисления площади и периметра прямоугольников. (Примечание: это не функции высшего порядка, поскольку они не принимают функцию в качестве аргумента). Хотя это совершенно правильный код JavaScript, давайте еще раз проверим, чего не хватает в приведенном выше коде. Если вы поняли это правильно. Это повторение кода.

Мы повторяем:

const output = [];

for(let i = 0; i < rectangles.length; i++){}

и,

return output;

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

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

const calculate = function(rectangles, logic){
  const output = [];
  for (let i = 0; i < rectangles.length; i++) {
    output.push(logic(rectangles[i]));
  }
  return output;
};
const area = function({ length, height }){
  return length * height;
};
console.log(calculate(rectangles, area)) // [ 40, 72, 39, 24 ]

Выглядит чистым. Правильно?

Пройдемся по строчке:

  1. Во-первых, мы определили нашу общую функцию, которая называется calculate. Он принимает два аргумента rectangle и logic. прямоугольники в нашем массиве и логика — это логика, которую мы хотим использовать для каждого прямоугольника.
  2. И внутри цикла мы использовали логику, которую мы можем применить к каждому прямоугольнику.
  3. Мы абстрагировали нашу логику области от функции и передали в качестве параметра, который принимает длину и высоту прямоугольника способом деструктурирования объекта.

Теперь давайте посмотрим, хотим ли мы вычислить периметр прямоугольников с помощью приведенного выше кода.

const calculate = function(rectangles, logic){
  const output = [];
  for (let i = 0; i < rectangles.length; i++) {
    output.push(logic(rectangles[i]));
  }
  return output;
};
const area = function({ length, height }){
  return length * height;
};
const perimeter = function({ length, height }){
  return 2 * (length + height);
};
console.log(calculate(rectangles, area)) // Area: [ 40, 72, 39, 24 ]
console.log(calculate(rectangles, perimeter)) // Perimeter: [ 28, 36, 32, 22 ]

Уууууу!! просто добавив 4 строки в приведенный выше код, мы также получим наш периметр.

Вы, должно быть, думаете, что этот парень такой Идиот. Тема была о функциях высшего порядка, но он затронул все (такие как DRY, многоразовые функции и т. д.), кроме HOF.

Да!! Ты прав. но при этом вы еще не поняли, что уже сделали свой первый HOF. Давайте вернемся на несколько шагов назад и проверим наш последний фрагмент кода. Кроме того, постарайтесь запомнить определение HOF.

Функция высшего порядка — это функция, которая получает функцию в качестве аргумента или возвращает функцию в качестве вывода.

И сейчас

const calculate = function(rectangles, logic){
  const output = [];
  for (let i = 0; i < rectangles.length; i++) {
    output.push(logic(rectangles[i].length, rectangles[i].height));
  }
  return output;
};

Да!! Здесь это calculate в нашей функции высшего порядка. который получает функцию logic в качестве одного из аргументов.

[БОНУС]Дополнительно всегда здорово!! если вы получите что-то бесплатно. Давайте сделаем некоторые дополнительные вещи в приведенном выше коде. Если сравнить нашу функцию calculate и функцию map в Javascript.

console.log(calculate(rectangles, area)) // [ 40, 72, 39, 24 ]
console.log(rectangles.map(area)) // [ 40, 72, 39, 24 ]

Эти две вещи делают одно и то же. Принимая функцию area в качестве аргумента, перебирая все прямоугольники в массиве и возвращая новый массив площади. Но вызывающее представление отличается в обеих реализациях. В calculate он принимает массив прямоугольников в качестве аргумента, но в map он представлен как rectangles.map() .

Давайте сделаем наш calculate таким же, как map

Для этого вам просто нужно сделать одну простую вещь.

Array.prototype.calculate = function(logic) {
  const output = [];
  for (let i = 0; i < this.length; i++) {
    output.push(logic(this[i]));
  }
  return output;
};

Вот и все. Итак, что мы сделали, так это добавили Array.prototype.calculate вместо const calculate и обработали наш прямоугольный объект внутри функции как this .

Array.prototype Это сделало функцию calculate доступной для каждого доступного массива, и мы можем получить доступ к вычислению (HOF) для каждого массива, который мы определяем, например: обр. вычислить(‹наша логическая функция›).

Смотрите волшебство!!

const rectangles = [
  { length: 10, height: 4 },
  { length: 12, height: 6 },
  {length: 13,height: 3,},
  { length: 8, height: 3 },
];
Array.prototype.calculate = function (logic) {
  const output = [];
  for (let i = 0; i < this.length; i++) {
    output.push(logic(this[i]));
  }
  return output;
};
const area = function ({ length, height }) {
  return length * height;
};
const perimeter = function ({ length, height }) {
  return 2 * (length + height);
};
console.log(rectangles.calculate(area)); // [ 40, 72, 39, 24 ]
console.log(rectangles.map(area)); // [ 40, 72, 39, 24 ]

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

Спасибо!! Удачного кодирования.