Чтобы выполнить предыдущий«XDM, как функциональное программирование на JS? Смотрите, хватит! (один)", мы знаем несколько основных концепций функционального программирования.
сделать здесьКраткий обзор:
- Цель функционального программирования — сделать поток данных более очевидным, чтобы код был более читабельным;
- Функции требуют одного или нескольких входных данных (в идеале только одного!)
- Замыкания являются основой функций высшего порядка;
- Будьте осторожны с анонимными функциями;
- устарел, это указывает на;
В этой статье речь пойдет о пункте 2.вход в функцию, это основа облегченного функционального программирования JS, это важно! ! !
частичная функция
Текущий статус
Мы часто пишем такой код:
function ajax(url,data,callback) {
// ..
}
function getPerson(data,cb) {
ajax( "http://some.api/person", data, cb );
}
ajaxФункция имеет три входных параметра, вgetPersonВызывается в функции, где был определен URL-адрес, и два параметра data и cb ожидают передачи. (Поскольку во многих случаях параметры в настоящее время не определены, вам нужно дождаться определения работы других функций, прежде чем продолжить передачу)
Но наш принцип таков: в идеале нужна только одна запись!
Как оптимизировать для достижения этого?
Возможно, мы сможем установить другую функцию во внешнем слое для дальнейшего определения параметров, таких как:
function getCurrentUser(cb) {
...// 通过某些操作拿到 CURRENT_USER_ID
getPerson( { user: CURRENT_USER_ID }, cb );
}
Таким образом, параметр данных также был определен, а параметр cb все еще ожидает передачи; функцияgetCurrentUserЕсть только одна запись!
Маршрут передачи данных:
ajax(url,data,callback) => getPerson(data,cb) => getCurrentUser(cb)
Таким образом, процесс постепенного уменьшения количества параметров функциичастичное применение.
Также известен как:getCurrentUser(cb)даgetOrder(data,cb)Частичная функция ,getOrder(data,cb)даajax(url,data,cb)функциональныйчастичная функция.
Представлять себе:
Если функция такая:
function receiveMultiParam(a,b,c,......,x,y,z){
// ..
}
Нужно ли нам по-прежнему вручную указывать внешнюю функцию для вложения слой за слоем, как указано выше?
Покажи, что мы этого не делаем!
инкапсулировать частичный
Нам нужно только инкапсулироватьpartial(..)функция:
function partial(fn,...presetArgs) {
return function partiallyApplied(...laterArgs){
return fn( ...presetArgs, ...laterArgs );
};
}
Его основная логика такова:
var partial =
(fn, ...presetArgs) =>
(...laterArgs) =>
fn( ...presetArgs, ...laterArgs );
Возьмите функцию в качестве аргумента! Помните, что мы говорили ранее:
Функция, которая принимает или возвращает одну или несколько функций, называется функцией высшего порядка.
мы занимаемpartial()Чтобы реализовать приведенный выше пример:
var getPerson = partial( ajax, "http://some.api/person" );
var getCurrentUser = partial( getPerson, { user: CURRENT_USER_ID } ); // 版本 1
Внутренний анализ следующих функций очень важен:
Рабочий механизм
getPerson()Внутренний рабочий механизм:
var getPerson = function partiallyApplied(...laterArgs) {
return ajax( "http://some.api/person", ...laterArgs );
};
getCurrentUser()Внутренний рабочий механизм:
var getCurrentUser = function outerPartiallyApplied(...outerLaterArgs) {
var getPerson = function innerPartiallyApplied(...innerLaterArgs){
return ajax( "http://some.api/person", ...innerLaterArgs );
};
return getPerson( { user: CURRENT_USER_ID }, ...outerLaterArgs );
}
Данные передаются:
getCurrentUser(outerLaterArgs) => getPerson(innerLaterArgs) => ajax(...params)
Мы добиваемся более мощной передачи данных за счет такого дополнительного слоя-обертки функций,
Мы передаем функцию, которая должна уменьшить ввод параметраpartial()как первый параметр, остальныеpresetArgs, некоторые известны в настоящее время, а некоторые могут быть записаны. Есть также неопределенные записиlaterArgs, вы можете продолжить добавление после подтверждения.
Наличие дополнительного уровня оберток функций высшего порядка, подобных этому, является сущностью функционального программирования!
"По мере продолжения этой серии статей мы будем объединять множество функций друг с другом. Помните, что это функциональное программирование!" - Облегченное функциональное программирование на JavaScript
По сути, реализацияgetCurrentUser()Вы также можете написать:
// 版本 2
var getCurrentUser = partial(
ajax,
"http://some.api/person",
{ user: CURRENT_USER_ID }
);
// 内部实现机制
var getCurrentUser = function partiallyApplied(...laterArgs) {
return ajax(
"http://some.api/person",
{ user: CURRENT_USER_ID },
...laterArgs
);
};
Но версия 1 более выразительна, поскольку в ней повторно используются уже определенные функции. Считается, что это больше в духе функционального программирования!
расширить частичный
Давайте посмотримpartial()Эту функцию можно использовать и другими способами:
function partial(fn,...presetArgs) {
return function partiallyApplied(...laterArgs){
return fn( ...presetArgs, ...laterArgs );
};
}
Например: добавляем 3 к каждому элементу массива [1,2,3,4,5], обычно делаем так:
function add(x,y) {
return x + y
[1,2,3,4,5].map( function adder(val){
return add( 3, val );
} );
// [4,5,6,7,8]
с помощьюpartial():
[1,2,3,4,5].map( partial( add, 3 ) );
// [4,5,6,7,8]
add(..) нельзя передать напрямую в функцию map(..), ее можно передать после обработки частичным приложением;
Фактически,partial()Функции также могут иметь множество вариантов:
Вспомните, как мы ранее вызывали функцию Ajax: ajax( url, data, cb ). Что нам делать, если мы хотим частично применить cb и указать параметры data и url позже?
function reverseArgs(fn) {
return function argsReversed(...args){
return fn( ...args.reverse() );
};
}
function partialRight( fn, ...presetArgs ) {
return reverseArgs(
partial( reverseArgs( fn ), ...presetArgs.reverse() )
);
}
var cacheResult = partialRight( ajax, function onResult(obj){
cache[obj.id] = obj;
});
// 处理后:
cacheResult( "http://some.api/person", { user: CURRENT_USER_ID } );
карри
Функция Collin на самом деле является специальной частью функции.
Мы используем функцию Curry (..) для реализации предыдущего примера AJAX (..), который бы выглядел так:
var curriedAjax = curry( ajax );
var personFetcher = curriedAjax( "http://some.api/person" );
var getCurrentUser = personFetcher( { user: CURRENT_USER_ID } );
getCurrentUser( function foundUser(user){ /* .. */ } );
Каррированная функция: принимает один аргумент (количество аргументов: 1) и возвращает другую функцию, которая принимает следующий аргумент.
Он преобразует функцию из вызываемой f(a, b, c) в вызываемую f(a)(b)(c).
выполнить:
function curry(fn,arity = fn.length) {
return (function nextCurried(prevArgs){
return function curried(nextArg){
var args = prevArgs.concat( [nextArg] );
if (args.length >= arity) {
return fn( ...args );
}
else {
return nextCurried( args );
}
};
})( [] );
}
резюме этапа
Почему мы так много внимания уделяем «частичным функциям» (partial(sum,1,2)(3)) или «каррированию» (sum(1)(2)(3))?
Во-первых, очевидно, что частичные функции или каррирование могут разделить время и место «указания отдельных аргументов»;
Во-вторых, и это более важно, когда функции имеют только один параметр, мы можем относительно легко их комбинировать. Эта единичная функция удобна для последующих комбинированных функций;
Обертка функции, чтобы сделать ее функцией более высокого порядка, является сутью функционального программирования!
Пока что с помощью оружейной пушки «частичной функции» мы постепенно приоткроем завесу облегченного функционального программирования JS ~
над.
Я Наггетс Энтони, публичный аккаунт [Наггетс Энтони], лайкните 👍 подписаться👀, вывод раскрывает ввод! Продолжайте следить!