Add (1) (2) (3). Всего === 6 - Кто-нибудь еще видел функции самоповторения, используемые как это?

Следующий код работает, и, хотя я понимаю, почему он работает, я его нигде не видел. Я предполагаю, что это связано с тем, что все другие шаблоны дизайна намного лучше.

Я бы все же ожидал увидеть этот пример как предостерегающий рассказ вдоль линии, но я этого не сделал.

Конечно, это ужасно, особенно с примером ниже, который я выбрал, потому что ясно, что он делает, но:

Что называется этим шаблоном?

Обычно ли он используется?

Есть ли законные проекты, которые используют этот шаблон?

var add = function container (val) {

  addFunc = function f (val, undefined) {
  addFunc.total += val;
  return addFunc;
  };

addFunc.total = 0;

return addFunc(val);
};

alert(add(1)(2)(3).total);
alert(add(1)(2)(33).total);

Изменить: изменение имени переменной, чтобы код работал в IE.

Ответ 1

Технически это можно рассматривать как цепочку или инкапсуляцию.

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

Кроме того, поскольку фактическое тело кода никогда не отображается вызывающему, это также можно считать инкапсуляцией, поскольку метод addFunc не подвергается внешней области.

Ответ 2

Это концепция функционального программирования, называемая currying.

По существу, с учетом function foo(a, b, c) вы создаете function bar(a), который возвращает function bar2(b), который возвращает function bar3(c), который дает окончательный ответ.

Технически это не истинное каррирование, потому что оно продолжается бесконечно и использует побочный эффект (свойство total), чтобы вырваться из бесконечного цикла.

Но в любом случае могут быть полезные приложения этого шаблона. Это особенно полезно для пересечения древовидных структур, где вы вычисляете некоторый результат для каждого листа дерева, где результат зависит от происхождения этого листа. Вы запускаете функцию curried в корневом каталоге node, а затем запускаете возвращаемую функцию для каждого дочернего элемента node, а затем для каждого из этих дочерних узлов и т.д. Чистая валютная функция возвращает другую функцию, если node it у него есть дети, и он вернет желаемое значение, если вы достигли листа.

Код будет простой рекурсивной функцией, которая передает себе новый "root" node и функцию для его синтаксического анализа, которая всегда принимает один аргумент.

Но способ, которым он используется здесь, больше похож на учебное упражнение, а не на что-то полезное.

EDIT: если вы хотите сделать его чистой функцией currying, но все еще имеете квази-бесконечную рекурсию, входные данные должны предоставить информацию о остановке (так же, как C-строка использует значение 0x00 для определения EOF):

var add = (function() {
    var total = 0;
    return function nextAdd(a) {
        if(a != null) {
            total += a;
            return nextAdd;
        } else {
            return total;
        }
    };
})();

Затем add(1)(2)(3)(null) === 6 и нет параметра <побочного эффекта .total.

Ответ 3

Это называется Currying wikipedia. От имени Haskell Curry wikipedia (но изначально разработанный Моисеем Ильичем Шонфинкелем wikipedia).

Метод преобразования функции, которая принимает несколько аргументов (или n-кортежей аргументов) таким образом, что ее можно назвать цепочки функций, каждая из которых имеет один аргумент (частичное приложение).

Из Шаблоны JavaScript в формате 2010:

Когда использовать Currying - когда вы вызываете одну и ту же функцию и передаете в основном те же параметры, функция, вероятно, является хорошим кандидатом для currying. Вы можете динамически создавать новую функцию, частично применяя набор аргументов к вашей функции. Новая функция сохранит сохраненные повторяющиеся параметры (поэтому вам не нужно передавать их каждый раз) и будет использовать их для предварительного заполнения полного списка аргументов, ожидаемых исходной функцией.

Еще одна статья для currying от Dustin Diaz.

Ответ 4

Вам было бы бесконечно лучше:

function add() {
    var l = arguments.length, i, sum = 0;
    for( i=0; i<l; i++) sum += arguments[i];
    return sum;
}
alert(add(1,2,3)); // 6

Действительно, не должно быть причин для стиля кода, о котором вы спрашиваете. Я не видел никакого легитимного использования, только произвольную длину arguments.