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

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

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

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

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

function compose(f,g) {

  return function() {

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

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

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

    return f.call(this, g.apply(this, arguments));

  };

}

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

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

var squareofsum = compose(square, sum);

squareofsum(2,3) // => 25

Функции partial() и memoize(), которые определяются в следующем разделе, представляют собой еще две важные функции высшего порядка.

8.8.3. Частичное применение функций

Метод bind() функции f (раздел 8.7.4) возвращает новую функцию, которая вызывает f в указанном контексте и с заданным набором аргументов. Можно сказать, что он связывает функцию с объектом контекста и частично применяет аргументы. Метод bind() применяет аргументы слева, т.е. аргументы, которые передаются методу bind(), помещаются в начало списка аргументов, передаваемых оригинальной функции. Однако есть возможность частичного применения аргументов справа:

// Вспомогательная функция преобразования объекта (или его части),

// подобного массиву, в настоящий массив. Используется ниже

// для преобразования объекта arguments в настоящий массив,

function array(a, n) { return Array.prototype.slice.call(a, n || 0); }

// Аргументы этой функции помещаются в начало списка

function partialLeft(f /*, ...*/) {

  var args = arguments; // Сохранить внешний массив аргументов

  return function() { // И вернуть эту функцию

    var а = array(args, 1); // Начиная с элемента 1 во внеш. масс,

    а = a.concat(array(arguments)); // Добавить внутренний массив аргум.

    return f.apply(this, а); // Вызвать f с этим списком аргументов

  };

}

// Аргументы этой функции помещаются в конец списка

function partialRight(f /*, ...*/) {

  var args = arguments; // Сохранить внешний массив аргументов

  return function() { // И вернуть эту функцию

    var а = array(arguments); // Начинать с внутр. масс, аргументов

    а = a.concat(array(args,1)); // Добавить внешние арг., начиная с 1.

    return f.apply(this, а); // Вызвать f с этим списком аргументов