Марейн Хавербеке - Выразительный JavaScript стр 19.

Шрифт
Фон

sum += number;

});

console.log(sum);

// → 15

Выглядит похоже на классический цикл 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;

};

}

Если f принимает больше одного параметра, она получит только первый. Можно было бы добавить кучу аргументов к внутренней функции (arg1, arg2 и т. д.) и передать все их в f, но ведь неизвестно, какого количества нам хватит. Кроме того, функция f не могла бы корректно работать с arguments.length. Так как мы всё время передавали бы одинаковое число аргументов, было бы неизвестно, сколько аргументов нам было задано изначально.

Для таких случаев у функций в JavaScript есть метод apply. Ему передают массив (или объект в виде массива) из аргументов, а он вызывает функцию с этими аргументами.

function transparentWrapping(f) {

return function() {

return f.apply(null, arguments);

};

}

Данная функция бесполезна, но она демонстрирует интересующий нас шаблон – возвращаемая ею функция передаёт в f все полученные ею аргументы, но не более того. Происходит это при помощи передачи её собственных аргументов, хранящихся в объекте arguments, в метод apply. Первый аргумент метода apply, которому мы в данном случае присваиваем null, можно использовать для эмуляции вызова метода. Мы вернёмся к этому вопросу в следующей главе.

JSON

Функции высшего порядка, которые каким-то образом применяют функцию к элементам массива, широко распространены в JavaScript. Метод forEach – одна из самых примитивных подобных функций. В качестве методов массивов нам доступно много других вариантов функций. Для знакомства с ними давайте поиграем с ещё одним набором данных.

Несколько лет назад кто-то обследовал много архивов и сделал целую книгу по истории моей фамилии. Я открыл её, надеясь найти там рыцарей, пиратов и алхимиков… Но оказалось, что она заполнена в основном фламандскими фермерами. Для развлечения я извлёк информацию по моим непосредственным предкам и перевёл в формат, пригодный для чтения компьютером.

Файл выглядит примерно так:

[

{"name": "Emma de Milliano", "sex": "f",

"born": 1876, "died": 1956,

"father": "Petrus de Milliano",

"mother": "Sophia van Damme"},

{"name": "Carolus Haverbeke", "sex": "m",

"born": 1832, "died": 1905,

"father": "Carel Haverbeke",

"mother": "Maria van Brussel"},

… и так далее

]

Этот формат называется JSON, что означает JavaScript Object Notation (разметка объектов JavaScript). Он широко используется в хранении данных и сетевых коммуникациях.

JSON похож на JavaScript по способу записи массивов и объектов – с некоторыми ограничениями. Все имена свойств должны быть заключены в двойные кавычки, а также допускаются только простые величины – никаких вызовов функций, переменных, ничего что включало бы вычисления. Также не допускаются комментарии.

JavaScript предоставляет функции JSON.stringify и JSON.parse, которые преобразовывают данные из этого формата и в этот формат. Первая принимает значение и возвращает строчку с JSON. Вторая принимает такую строчку и возвращает значение.

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке