Выбрать главу

  : function(a, f, initial) { // Этот алгоритм взят из спецификации ES5

  var і = 0, len = a.length, accumulator;

  // Использовать указанное начальное значение или первый элемент а

  if (arguments.length > 2)

    accumulator = initial;

  else { // Найти первый элемент массива с определенным значением

    if (len == 0) throw TypeError();

    while(i < len) {

      if (i in a) {

        accumulator = a[i++];

        break;

      }

      else i++;

    } 

    if (i == len) throw TypeError();

  }

  // Теперь вызвать f для каждого оставшегося элемента массива

  while(i < len) {

    if (і in а)

      accumulator = f.call(undefined, accumulator, a[i], i, a);

    i++;

  }

  return accumulator;

};

После определения этих функций map() и reduce() вычисление среднего и стандартного отклонения будет выглядеть так:

var data = [1,1,3,5,5];

var sum = function(x.y) { return x+y; };

var square = function(x) { return x*x; };

var mean = reduce(data, sum)/data.length;

var deviations = map(data, function(x) {return x-mean;});

var stddev = Math.sqrt(reduce(map(deviations, square), sum)/(data.length-1));

8.8.2. Функции высшего порядка

Функции высшего порядка - это функции, которые оперируют функциями, принимая одну или более функций и возвращая новую функцию. Например:

// Эта функция высшего порядка возвращает новую функцию, которая передает свои аргументы

// функции f и возвращает логическое отрицание значения, возвращаемого функцией f;

function not(f) {

  return function() { // Возвращает новую функцию

    var result = f.apply(this, arguments); // вызов f

    return !result; // и инверсия результата.

  };

}

var even = function(x) { // Функция, определяющая четность числа

  return х % 2 === 0;

};

var odd = not(even); // Новая функция, выполняющая противоположную операцию

[1,1,3,5,5].every(odd); // => true: все элементы массива нечетные

Функция not() в примере выше является функцией высшего порядка, потому что она принимает функцию в виде аргумента и возвращает новую функцию. В качестве еще одного примера рассмотрим функцию mаррег(), представленную ниже. Она принимает функцию в виде аргумента и возвращает новую функцию, которая отображает один массив в другой, применяя указанную функцию. Данная функция использует функцию mар(), которая была определена выше, и важно понимать, чем отличаются эти две функции:

// Возвращает функцию, которая принимает массив в виде аргумента, применяет функцию f

// к каждому элементу и возвращает массив возвращаемых значений.

// Эта функция отличается от функции тар(), представленной выше,

function mapper(f) {

  return function(a) { return map(a, f); };

}

var increment = function(x) { return x+1; };

var incrementer = mapper(increment);

incrementer([1,2,3]) // => [2,3,4]

Ниже приводится пример еще одной, более универсальной функции, которая принимает две функции, f и g, и возвращает новую функцию, которая возвращает результат f(g()):

// Возвращает новую функцию, которая вычисляет f(g(...)). Возвращаемая функция h

// передает все свои аргументы функции g, затем передает значение, полученное от g,

// функции f и возвращает результат вызова f. Обе функции, f и g,

// вызываются с тем же значением this, что и h.

function compose(f,g) {

  return function() {

    // Для вызова f используется call, потому что ей передается

    // единственное значение, а для вызова g используется apply,

    // потому что ей передается массив значений,