Перевод статьи Enmanuel Durán — Higher order functions and some great applications in javascript
Функции высшего порядка (Higher order functions HOF) являются очень мощным понятием, в двух словах, можно сказать, что HOF — это функция, которая принимает в качестве аргумента другую функцию и/или возвращает функцию, поэтому, основываясь на этом, мы могли бы сказать, что они являются функциями более высокого порядка, потому что они действуют как «родитель» или «обертка» для других функций.
Допустим, у нас есть задача:
Реализуйте функцию, которая считает от заданной начальной точки startingPoint до 100, если заданная точка является нечетным числом, функция будет считать с интервалами в 5, если, число будет четным, то будет считаться с интервалами в 10. Так же нужно что бы пользователь мог запустить счетчик сразу после указания начальной точки, и отложено. То есть в начале программы должно указываться startingPoint, а где нибудь позже в программе должно вычислиться значение счетчика.
Итак, первая реализация этой задачи без использования функций более высокого порядка может выглядеть так:
const counterToOneHundred = startingPoint => { const isOdd = startingPoint % 2; const interval = isOdd ? 5 : 10; for (let i = startingPoint; i < 100; i += interval) { console.log(`${i} of 100`); } };
Отлично, все работает … верно? давайте посмотрим наш контрольный список:
СТОП! мы пропустили одно требование, хотя мы почти сделали его, давайте попробуем проверить последний элемент нашего списка:
const startingPoint = 5; // starting point being any number const counterToOneHundred = () => { const isOdd = startingPoint % 2; const interval = isOdd ? 5 : 10; for (let i = startingPoint; i < 100; i += interval) { console.log(`${i} of 100`); } };
Теперь, поскольку мы вывели startingPoint из области действия функции, мы можем выполнить счетчик независимо от определения переменной, а это означает, что мы можем выполнить последние требование задачи:
Вау! это было не так плохо, правда? но подождите, есть пара вещей, которые нам здесь не хватает:
Это не хорошо …
Меньше слов, больше кода:
const counterToOneHundred = startingPoint => { const isOdd = startingPoint % 2; const interval = isOdd ? 5 : 10; return () => { for (let i = startingPoint; i < 100; i += interval) { console.log(`${i} of 100`); } }; };
БУМ! вот и все, хорошего дня … шучу, теперь давайте посмотрим наш новый контрольный список и затем объясним нетривиальные моменты:
контрольный список
Да. Когда мы выполняем нашу функцию наподобие counterToOneHundred(1)(), мы определяем переменные и возвращаем определение анонимной функции внутри в первом вызове функции, а затем выполняем внутреннюю функцию во втором вызове.
Да. Мы можем сохранить возвращение первого вызова функции, а затем вызвать внутреннюю функцию при необходимости:
Приведенный ниже код сохраняет определение анонимной дочерней функции в переменной и выполняет вычисления интервала.
const counter = counterToOneHundred(1);
Затем мы запускаем счетчик на более позднем этапе, когда это необходимо
counter();
Поскольку все переменные находятся внутри области действия функции, это положительно.
Таким образом, используя HOF, мы смогли
Теперь достаточно счетчиков, давайте использовать HOF для лучшего примера, более реалистичного. Представьте, что нам нужно создать три кнопки общего доступа, чтобы опубликовать нашу текущую страницу в Twitter, Facebook или Linkedin, эти кнопки откроют всплывающее окно при нажатии на их в зависимости от типа кнопки.
Реализация этого может выглядеть примерно так:
const share = () => { const pageUrl = 'https://enmascript.com'; const pageTitle = 'A place to share about web development and science'; const networks = { twitter: `https://twitter.com/share?url=${pageUrl}&text=${pageTitle}`, facebook: `https://www.facebook.com/sharer/sharer.php?u=${pageUrl}`, linkedIn: `https://www.linkedin.com/shareArticle?mini=true&url=${pageUrl}` }; /** * получаем сеть и возвращаем функцию открытия окна */ return network => event => { event.preventDefault(); /* если указана не правильная сеть выходим */ if (!(network in networks)) { return false; } /* открытие окна в зависимости от выбранной сети */ const networkWindow = window.open( networks[network], 'network-popup', 'height=350, width=600' ); /* Применение фокуса к всплывающему окну после его открытия. */ if (networkWindow.focus) { networkWindow.focus(); } }; };
И возможное использование этого (скажем, на React) будет выглядеть примерно так:
/* We setup the data once */const shareOn = share(); /* We validate each network and open the popup on click */<div onClick={shareOn('twitter')}><Twitter /></div> <div onClick={shareOn('facebook')}><Facebook /></div> <div onClick={shareOn('linkedIn')}><LinkedIn /></div>
Круто, верно? В этой реализации мы также используем концепцию Currying, но это тема, которую я предпочел бы затронуть в другой статье.
Существует множество приложений для функций высшего порядка, ниже некоторых функций, реализованных с помощью этого подхода.
Позволяет легко отлавливать ошибки JavaScript, передавая определение функции, оно автоматически пытается выполнить ее, а если происходит сбой, затем отправляет аварийное сообщение, вы можете заменить аварийное действие любым, чем захотите.
Реализация
function errorCatcher(cb) { try { cb(); } catch (error) { console.log('Ups, Looks like something went wrong!'); } }
Использование
function sayHi() { const person = { name: 'Daniel' }; console.log(`Hi, ${person.name} ${person.career.name}`); } errorCatcher(sayHi);
Управляет выполнением функции throttledFn, чтобы она выполнялась с интервалами delayTime, особенно полезно, чтобы избежать выполнения событий с повышенным числом последовательных выполнений (события прокрутки, события изменения размера).
Реализация
function throttle(throttledFn, delayTime) { let lastCallTime = 0; return (...args) => { const currentCallTime = new Date().getTime(); if (currentCallTime - lastCallTime < delayTime) return; lastCallTime = currentCallTime; throttledFn(...args); }; }
Использование
function logger() { console.log(`I'm executed every 200ms when actively scrolling`); } window.addEventListener('scroll', throttle(logger, 200));
Проверяет время выполнения функции.
Реализация
function performance(fn) { console.time('fn'); fn(); console.timeEnd('fn'); }
Использование
function loop() { for (i = 0; i < 1000; i++) { console.log('executing loop to 1000'); } } performance(loop);
Как вы видите, функции высшего порядка очень полезны, они широко используются, и вы, возможно, использовали их, не замечая этого, они применяются в объектно-ориентированном программировании при использовании шаблона декоратора, они также используются в библиотеках, таких как express и redux ,
Я надеюсь, что вы нашли эту статью полезной, если вы действительно поделитесь со своими друзьями, также вы можете подписаться на меня в Twitter, увидимся в следующем, ребята.
Хотите оставить комментарий? Сделай это в twitter
Краткий перевод: https://vuejs.org/guide/components/v-model.html Основное использование v-model используется для реализации двусторонней привязки в компоненте. Начиная с Vue…
Сегодня мы рады объявить о выпуске Vue 3.4 «🏀 Slam Dunk»! Этот выпуск включает в…
Vue.js — это универсальный и адаптируемый фреймворк. Благодаря своей отличительной архитектуре и системе реактивности Vue…
Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с…
Каким бы ни было ваше мнение о JavaScript, но всем известно, что работа с датами…
Все, кто следит за последними событиями в мире адаптивного дизайна, согласятся, что введение контейнерных запросов…