Выглядит похоже на классический цикл for
forEach. Поэтому его нужно закрыть как фигурной, так и круглой скобкой.Используя этот шаблон, мы можем задать имя переменной для текущего элемента массива (number
Вообще, нам даже не нужно писать самим forEach
forEach принимает только один аргумент – функцию, которую нужно выполнить для каждого элемента.Для демонстрации удобства этого подхода вернёмся к функции из предыдущей главы. Она содержит два цикла, проходящих по массивам:
function gatherCorrelations(journal) {
var phis = {};
for (var entry = 0; entry < journal.length; entry++) {
var events = journal[entry].events;
for (var i = 0; i < events.length; i++) {
var event = events[i];
if (!(event in phis))
phis[event] = phi(tableFor(event, journal));
}
}
return phis;
}
Используя forEach
function gatherCorrelations(journal) {
var phis = {};
journal.forEach(function(entry) {
entry.events.forEach(function(event) {
if (!(event in phis))
phis[event] = phi(tableFor(event, journal));
});
});
return phis;
}
Функции высшего порядка
Функции, оперирующие другими функциями – либо принимая их в качестве аргументов, либо возвращая их, называются функциями высшего порядка
. Если вы уже поняли, что функции – это всего лишь переменные, ничего особенного в существовании таких функций нет. Термин происходит из математики, где различия между функциями и другими значениями воспринимаются более строго.Функции высшего порядка позволяют нам абстрагировать действия, а не только значения. Они бывают разными. Например, можно сделать функцию, создающую новые функции.
function greaterThan(n) {
return function(m) { return m > n; };
}
var greaterThan10 = greaterThan(10);
console.log(greaterThan10(11));
// → true
Можно сделать функцию, меняющую другие функции.
function noisy(f) {
return function(arg) {
console.log("calling with", arg);
var val = f(arg);
console.log("called with", arg, "- got", val);
return val;
};
}
noisy(Boolean)(0);
// → calling with 0
// → called with 0 - got false
Можно даже делать функции, создающие новые типы управления потоком выполнения программы.
function unless(test, then) {
if (!test) then();
}
function repeat(times, body) {
for (var i = 0; i < times; i++) body(i);
}
repeat(3, function(n) {
unless(n % 2, function() {
console.log(n, "is even");
});
});
// → 0 is even
// → 2 is even
Правила лексических областей видимости, которые мы обсуждали в главе 3, работают нам на пользу в таких случаях. В последнем примере переменная n
n. Тела таких внутренних функций имеют доступ к переменным, окружающим их. Они могут играть роль блоков {}, используемых в обычных циклах и условных выражениях. Важное отличие в том, что переменные, объявленные внутри внутренних функций, не попадают в окружение внешней. И обычно это только к лучшему.Передача аргументов
Функция noisy
function noisy(f) {
return function(arg) {
console.log("calling with", arg);
var val = f(arg);
console.log("called with", arg, "- got", val);
return val;
};
}