#javascript #function
#javascript #функция #метод-объединение в цепочку #функция-композиция
Вопрос:
Допустим, у меня есть список функций, хранящихся в массиве:
var myFunctions = [
function (i) {return i 2},
function (i) {return i * 2},
function (i) {return i - 3}
]
Каков был бы наилучший способ последовательно вызвать все эти функции объекта, т. е. получить ((n 2) * 2) - 3
в результате?
Приветствуются ответы с использованием внешних библиотек, таких как подчеркивание 🙂
Ответ №1:
Массивы также являются объектами JavaScript. В вашем случае вы создали массив и три его свойства, а именно f1
, f2
и f3
. Вместо этого вы можете просто сделать
var myFunctions = [
function(i) {
return i 2
},
function(i) {
return i * 2
},
function(i) {
return i - 3
}
];
Теперь, когда у нас есть массив функций, мы можем использовать Array.prototype.reduce
function для применения этих функций следующим образом
var result = myFunctions.reduce(function(result, currentFunction) {
return currentFunction(result);
}, n);
n
— это фактическое начальное значение, которое должно быть передано в список функций, которые будут применены. reduce
принимает начальное значение и первую функцию и передает их как result
и currentFunction
соответственно. Мы применяем currentFunction
on result
и возвращаем значение. На следующей итерации возвращаемым значением будет result
, а currentFunction
будет вторая функция и так далее.
Если вам не нравится функциональный подход, вы можете просто использовать цикл for, например, так
var i = 0, result = 0, n = 10;
for (var i = 0; i < myFunctions.length; i = 1) {
n = myFunctions[i](n);
}
Ответ №2:
Использование fold (уменьшить):
var n = 5;
var myFunctions = [
function (i) {return i 2},
function (i) {return i * 2},
function (i) {return i - 3}
];
n = myFunctions.reduce(function(n, fn) { return fn(n) }, n);
n; // => 11 ((5 2) * 2 - 3)
Использование композиции функций:
var myFunctions = [
function (i) {return i - 3},
function (i) {return i * 2},
function (i) {return i 2}
];
_.compose.apply(null, myFunctions)(5); // => 11
Обратите внимание, что во втором примере функции выполняются в обратном порядке, по соглашению последняя функция в цепочке применяется первой.
Ответ №3:
Передача исходного запроса @Sacha и ответа @thefourtheye посредством небольшого анонимного вызова функции, это может быть выражено следующим образом:
const inception = 42; // or anything you prefer really.
const modifiers = [
i => i - 3,
i => i * 2,
i => i 2
];
// Apply successively each generated function on its predecessor result,
// taking inception as initial origin.
modifiers.reduce((origin, transform) => transform(origin), inception)
Обратите также внимание, что в этом фрагменте используются только константы, которые лучше отражают тот факт, что исходные параметры никогда не изменяются.