Как основанное на функциональном программировании приложение JavaScript размечается?

Я работал с node.js некоторое время на приложении чата (я знаю, очень исходный, но я полагал, что это будет хороший проект изучения). Underscore.js обеспечивает много понятий функционального программирования, которые выглядят интересными, таким образом, я хотел бы понять, как функциональная программа в JavaScript будет установкой.

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

var external;
function foo() {
   external = 'bar';
}
foo();

создал бы побочный эффект, корректный? Таким образом, как общее правило, Вы не хотите нарушать переменные в глобальной области видимости.

Хорошо, поэтому как это работает, когда Вы имеете дело с объектами и что нет? Например, много времен, у меня будут конструктор и init метод, который инициализирует объект, как так:

var Foo = function(initVars) {
   this.init(initVars);
}

Foo.prototype.init = function(initVars) {
   this.bar1 = initVars['bar1'];
   this.bar2 = initVars['bar2'];
   //....
}

var myFoo = new Foo({'bar1': '1', 'bar2': '2'});

Таким образом, мой init метод намеренно вызывает побочные эффекты, но каков был бы функциональный способ обработать тот же вид ситуации?

Кроме того, если кто-либо мог бы указать на меня или на Python или на исходный код JavaScript программы, которая пытается быть максимально функциональной, который также очень ценился бы. Я чувствую, что я близко к "получению его", но я просто не совсем там. Главным образом я интересуюсь тем, как работы функционального программирования с традиционным понятием классов ООП (или покончил с ним для чего-то другого, если это так).

29
задан Paul D. Waite 11 November 2010 в 14:41
поделиться

4 ответа

Вы должны прочитать этот вопрос:

Javascript как функциональный язык

Есть много полезных ссылок, в том числе:

А теперь на мой взгляд. Многие люди неправильно понимают JavaScript , возможно, потому, что его синтаксис похож на большинство других языков программирования (где Lisp / Haskell / OCaml выглядят совершенно иначе). JavaScript не объектно-ориентированный, это фактически язык, основанный на прототипах . У него нет классов или классического наследования, поэтому его не стоит сравнивать с Java или C ++.

JavaScript может быть лучше по сравнению с Lisp; у него есть замыкания и первоклассные функции. Используя их, вы можете создавать другие методы функционального программирования, такие как частичное приложение (каррирование).

Давайте возьмем пример (используя sys.puts из node.js):

var external;
function foo() {
    external = Math.random() * 1000;
}
foo();

sys.puts(external);

Чтобы избавиться от глобальных побочных эффектов, мы можем заключить его в закрытие:

(function() {
    var external;
    function foo() {
        external = Math.random() * 1000;
    }
    foo();

    sys.puts(external);
})();

Обратите внимание, что мы можем 'Фактически ничего не делать с external или foo вне области видимости. Они полностью закутаны в собственное закрытие, неприкасаемые.

Теперь, чтобы избавиться от внешнего побочного эффекта:

(function() {
    function foo() {
        return Math.random() * 1000;
    }

    sys.puts(foo());
})();

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

Я также хочу отметить, что смешивать функциональное программирование с объектами - это прекрасно. Возьмем, к примеру, следующее:

var Square = function(x, y, w, h) {
   this.x = x;
   this.y = y;
   this.w = w;
   this.h = h;
};

function getArea(square) {
    return square.w * square.h;
}

function sum(values) {
    var total = 0;

    values.forEach(function(value) {
        total += value;
    });

    return total;
}

sys.puts(sum([new Square(0, 0, 10, 10), new Square(5, 2, 30, 50), new Square(100, 40, 20, 19)].map(function(square) {
    return getArea(square);
})));

Как видите, использование объектов в функциональном языке может быть прекрасным. В некоторых Лиспах даже есть так называемые списки свойств, которые можно рассматривать как объекты.

Настоящая уловка при использовании объектов в функциональном стиле состоит в том, чтобы убедиться, что вы не полагаетесь на их побочные эффекты, а вместо этого относитесь к ним как к неизменяемым. Самый простой способ - всякий раз, когда вы хотите изменить свойство, просто создайте объект new с новыми деталями и вместо этого передайте его (этот подход часто используется в Clojure и Haskell).

Я твердо верю, что функциональные аспекты могут быть очень полезны в JavaScript, но в конечном итоге вы должны использовать все, что делает код более читабельным и что работает для вас.

30
ответ дан 28 November 2019 в 01:54
поделиться

Я думаю, http://documentcloud.github.com/underscore / должен хорошо подходить для того, что вам нужно - он предоставляет наиболее важные функции высшего порядка для функционального программирования и не имеет клиентских функций для манипулирования DOM, которые вам не нужны на стороне сервера. Хотя опыта у меня нет.

В качестве примечания: IMHO основной особенностью функционального программирования является Ссылочная прозрачность функции - результат функции зависит только от ее параметров - функция не зависит от изменений других объектов и не вносит никаких изменений кроме его значения результата. Это позволяет легко рассуждать о правильности программы и очень ценно для реализации предсказуемой многопоточности (если применимо). Хотя JavaScript не является лучшим языком для FP, я ожидаю, что использование неизменяемых структур данных будет очень дорогостоящим с точки зрения производительности.

2
ответ дан 28 November 2019 в 01:54
поделиться

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

Функциональное программирование - это вычисления без сохранения состояния. Объектно-ориентированное программирование - это все о переходах между состояниями. (Парафазирование this . Надеюсь, не так уж и плохо)

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

Если вы хотите быть более прагматичными в этом отношении, есть некоторые источники вдохновения из чисто функционального мира, которые вы могли бы использовать.

Я стараюсь придерживаться следующих правил:

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

Следуя этим правилам, можно получить ряд преимуществ:

  1. Простота повторного использования. Чем длиннее и сложнее функция, тем она более специализирована и, следовательно, тем меньше вероятность того, что ее можно будет использовать повторно. Обратное следствие состоит в том, что более короткие функции имеют тенденцию к более общему и, следовательно, их легче использовать повторно.

  2. Надежность кода.О правильности кода легче рассуждать, если он менее сложный.

  3. Легче тестировать функции, когда они делают только одно. Таким образом, будет меньше особых случаев для тестирования.

Обновление:

Включено предложение из комментария.

Обновление 2:

Добавлены полезные ссылки.

5
ответ дан 28 November 2019 в 01:54
поделиться

Итак, две вещи, на которые стоит обратить внимание,

  1. В вашем первом примере ваша переменная не будет просачиваться в глобальную область, и это то, как это должно происходить, постарайтесь никогда не использовать переменные без их объявления, т.е. test = 'data' вызовут утечку данных в глобальную область.

  2. Ваш второй пример также верен, bar1 и bar2 будут объявлены только в объекте Foo.

О чем следует помнить: старайтесь не злоупотреблять прототипированием, поскольку оно применимо к каждому создаваемому вами объекту, это может потребовать очень много памяти в зависимости от того, насколько сложны ваши объекты.

Если вы ищете фреймворк для разработки приложений, обратите внимание на ExtJs . Лично я думаю, что это идеально вписалось бы в модель, против которой вы пытаетесь развиваться. Просто помните, как работает их модель лицензирования, прежде чем в нее вкладывать большие средства.

0
ответ дан 28 November 2019 в 01:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: