предисловие
Эта статья в основном с точки зрения 3W (что, как, почему), чтобы объяснить простым для понимания образом, что такое каррирование функций и как его реализовать с помощью трех строк кода.add(1)(2)(3)
Это очень распространенный вопрос на собеседовании.
Что такое функция каррирования (карри)
Каррирование функций — это концепция функционального программирования. Концепция карри проста: вызовите функцию только с подмножеством аргументов и заставьте ее вернуть функцию для обработки остальных аргументов.
Проще говоря: каждый раз, когда функция вызывается, она принимает только подмножество аргументов и возвращает функцию до тех пор, пока не будут переданы все аргументы.
дать 🌰 Измените приведенную ниже функцию, которая принимает два аргумента, на функцию, принимающую один.
const add = (x, y) => x + y;
add(1, 2);
Измените его на функцию, которая принимает только один параметр за раз.
const add = x => y => x + y;
add(1)(2);
Каррирование, неизменяемые типы данных, чистые функции и т. д. — все это концепции функционального программирования. Эти концепции распространены в React, потому что в React много концепций функционального программирования. Чтобы узнать больше о том, что такое функциональное программирование, см.Руководство по функциональному программированию JS
add(1)(2)(3)
Мы можем сначала попробовать написать add(1)(2)(3)
const add = x => y => z => x + y + z;
console.log(add(1)(2)(3));
Это не кажется таким уж сложным, но что, если запрос интервьюера состоит в том, чтобы реализовать функцию добавления, которая одновременно поддерживает следующие варианты использования?
add(1, 2, 3);
add(1, 2)(3);
add(1)(2, 3);
Если мы по-прежнему будем следовать изложенному выше ходу мыслей, нужно ли нам писать много...
Конечно, мы можем сами реализовать вспомогательную функцию для генерации каррированных функций.
В чем основная идея? Чтобы определить, больше или равно ли количество параметров (args.length), переданных в функцию, количеству параметров, требуемых исходной функцией (fn.length), или равно, если да, то выполнить текущую функция; если меньше, то вернуть функцию.
const curry = (fn, ...args) =>
// 函数的参数个数可以直接通过函数数的.length属性来访问
args.length >= fn.length // 这个判断很关键!!!
// 传入的参数大于等于原始函数fn的参数个数,则直接执行该函数
? fn(...args)
/**
* 传入的参数小于原始函数fn的参数个数时
* 则继续对当前函数进行柯里化,返回一个接受所有参数(当前参数和剩余参数) 的函数
*/
: (..._args) => curry(fn, ...args, ..._args);
function add1(x, y, z) {
return x + y + z;
}
const add = curry(add1);
console.log(add(1, 2, 3));
console.log(add(1)(2)(3));
console.log(add(1, 2)(3));
console.log(add(1)(2, 3));
Ramda
RamdaВсе функции поддерживают каррирование. Другими словами, все многопараметрические функции могут по умолчанию использовать однопараметрические функции.
Или возьмем пример выше
const addThreeNumbers = (x, y, z) => x + y + z;
const curriedAddaddThreeNumbers = R.curry(addThreeNumbers);
const f = curriedAddaddThreeNumbers(1, 2);
console.log(f(3));
известныйlodashФункция каррирования также предусмотрена в , тогда она иRamda
какие различия есть
lodash
Это очень мощная библиотека функций инструментов, таких как дросселирование, защита от сотрясений, глубокое копирование и т. д. Пока введен lodash, мы можем использовать его напрямую.Ramda
это библиотека стилей функционального программирования.
Что делает каррирование?
Есть 3 основные функции:Повторное использование параметра,вернуться пораньшеиотложенное исполнение
Кратко объясним:
Повторное использование параметра: возьмите вышеуказанноеf
Например, этой функции нужно передать только один параметрz
, выполнить, результат1 + 2 + z
В результате два параметра 1 и 2 можно использовать повторно напрямую.
Ранний возврат и отложенное выполнение также хорошо понятны, потому что каждый раз, когда функция вызывается, она принимает только подмножество аргументов и возвращает функцию (ранний возврат), пока не будут переданы все аргументы (отложенное выполнение).