Оригинальная статья: Nick Scialli — What is a Higher-Order Function?
Одним из терминов, которые вы можете услышать в мире JavaScript, является «функция высшего порядка». В этой статье мы рассмотрим, что такое функция высшего порядка, на базе нескольких примеров.
По определению, функция высшего порядка — это функция, которая либо принимает функцию в качестве аргумента, либо возвращает функцию.
Если вы не знакомы с обработкой функций как first class objects, вы удивитесь, но это возможно. А так же, чрезвычайно полезно!
Давайте рассмотрим пару простых примеров: один для функции, которая принимает функцию в качестве аргумента, и другой, который возвращает функцию.
Давайте создадим относительно бесполезную функцию под названием evaluatesToFive, которая принимает два аргумента: первый аргумент будет числом, а второй аргумент будет функцией. Внутри нашей функции evaluatesToFive мы проверим, возвращает ли функция число пять.
function evaluatesToFive(num, fn) { return fn(num) === 5; }
Мы можем это проверить следующим образом:
function divideByTwo(num) { return num / 2; } evaluatesToFive(10, divideByTwo); // true evaluatesToFive(20, divideByTwo); // false
Немного бесполезно, но это круто, что мы можем это сделать!
В нашем следующем примере мы собираемся создать функцию, которая возвращает функцию. Наша функция будет называться multiplyBy. Она примет число в качестве аргумента и вернет новую функцию, которая умножит свой входной аргумент на это число.
function multiplyBy(num1) { return function(num2) { return num1 * num2; }; }
Теперь мы увидим как это можно использовать, создав пару функций умножения:
const multiplyByThree = multiplyBy(3); const multiplyByFive = multiplyBy(5); multipyByThree(10); // 30 multiplyByFive(10); // 50
Опять же, не супер полезно в его нынешнем виде, но довольно круто, несмотря ни на что.
Более полезным примером функций высшего порядка будет создание объекта валидатора. Основная идея — это будет функция, которая принимает объект в качестве аргумента, а затем любое количество функций, которые должны вернуть значение true, чтобы объект считался действительным.
В этом примере мы будем обрабатывать объект newUser и пытаться определить, следует ли нам разрешить ему регистрироваться в нашем приложении. Пользователь должен соответствовать следующим критериям:
Идеальный объект newUser будет выглядеть примерно так:
const newUser = { age: 24, password: 'some long password', agreeToTerms: true, };
Основываясь на этих знаниях, мы можем создать некоторые тестовые функции, которые возвращают значение true, когда наши желаемые условия выполняются, и false в противном случае.
function oldEnough(user) { return user.age >= 18; } function passwordLongEnough(user) { return user.password.length >= 8; } function agreeToTerms(user) { return user.agreeToTerms === true; }
Теперь мы можем создать функцию, которая принимает любое количество аргументов. Первым аргументом будет объект, который мы пытаемся проверить, а остальные аргументы будут функциями тестирования, которые будут использоваться для тестирования нашего объекта.
function validate(obj, ...tests) { for (let i = 0; i < tests.length; i++) { if (tests[i](obj) === false) { return false; } } return true; }
Рассмотрим что именно здесь происходит:
Теперь мы используем нашу функцию проверки, проверяя пару потенциальных новых пользовательских объектов:
const newUser1 = { age: 40, password: 'tncy4ty49r2mrx', agreeToTerms: true, }; validate(newUser1, oldEnough, passwordLongEnough, agreeToTerms); // true const newUser2 = { age: 40, password: 'short', agreeToTerms: true, }; validate(newUser2, oldEnough, passwordLongEnough, agreeToTerms); // false
Объект newUser1 правильно считается действительным, а объект newUser2 определяется как недействительный, поскольку его пароль слишком короткий.
Если мы применяем нашу функцию validate для нескольких пользователей, вероятно, лучше не повторять одни и те же тесты снова и снова. Вместо этого у нас может быть функция createValidator, которая возвращает валидатор объекта. В этом случае мы создадим userValidator, который применяет те же тестовые функции к любому пользователю, которого мы пытаемся проверить.
function createValidator(...tests) { return function(obj) { for (let i = 0; i < tests.length; i++) { if (tests[i](obj) === false) { return false; } } return true; }; }
Давайте посмотрим, как это дает нам более согласованный интерфейс, когда мы снова проверяем наши объекты newUser1 и newUser2:
const userValidator = createValidator( oldEnough, passwordLongEnough, agreeToTerms ); userValidator(newUser1); // true userValidator(newUser2); // false
Потрясающие! Теперь вы знаете как используя функцию более высокого порядка createValidator, использовать разные критерии проверки для различных объектов.
Краткий перевод: https://vuejs.org/guide/components/v-model.html Основное использование v-model используется для реализации двусторонней привязки в компоненте. Начиная с Vue…
Сегодня мы рады объявить о выпуске Vue 3.4 «🏀 Slam Dunk»! Этот выпуск включает в…
Vue.js — это универсальный и адаптируемый фреймворк. Благодаря своей отличительной архитектуре и системе реактивности Vue…
Недавно, у меня истек сертификат и пришлось заказывать новый и затем устанавливать на хостинг с…
Каким бы ни было ваше мнение о JavaScript, но всем известно, что работа с датами…
Все, кто следит за последними событиями в мире адаптивного дизайна, согласятся, что введение контейнерных запросов…
View Comments
Не знала про функцию first class objects, действительно очень полезная функция, изучу более детально.
Спасибо за заметку.
Мой вариант:
const createValidator = (fn, ...tests) => obj => {
for (const test of tests) {
if (test(obj) === false) return;
}
fn(obj)
}
const userValidator = createValidator(
greet = obj => console.log(`hi ${obj?.name}`),
oldEnough,
passwordLongEnough,
agreeToTerms
)