Вы должны прочитать этот вопрос:
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
вне области видимости. Они полностью завернуты в свое собственное закрытие, неприкасаемые.
Теперь, чтобы избавиться от побочного эффекта external
:
(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);
})));
Как видите, использование объектов на функциональном языке может быть просто нормальным. В некоторых Лиспах даже есть вещи, называемые списками свойств, которые можно рассматривать как объекты.
Реальный трюк с использованием объектов в функциональном стиле - убедиться, что вы не полагаетесь на их побочные эффекты, а вместо этого рассматриваете их как неизменные. Самый простой способ - всякий раз, когда вы хотите изменить свойство, просто создайте новый объект с новыми деталями и передайте его вместо этого (этот подход часто используется в Clojure и Haskell).
Я твердо верю, что функциональные аспекты могут быть очень полезны в JavaScript, но в конечном итоге вы должны использовать все, что делает код более читабельным, и то, что работает для вас.