JavaScript — очень универсальный язык, так как он может использоваться для процедурного, объектно-ориентированного или даже функционального программирования.
Например, вы можете легко определить анонимные функции в JavaScript в любой точке выполнения:
var f = function() { ... };
Эти функции могут передаваться как переменные, удовлетворяющие одной из предпосылок функционального программирования:
doSomething(f, ...);
Анонимные функции становятся замыканиями, автоматически связываясь с существующими переменными каждый раз, когда вы цитируете их в реализации:
var selector = '#someId';
var html = function(content) { $(selector).html(content); };
Расширяя шаблон, также очень легко определить функции, которые возвращают другие функции:
var write = function(selector) {
var html = function(content) { $(selector).html(content); };
};
реализовать какую-то конкретную версию карри.
Underscore.js
Есть несколько проблем с функциональным JavaScript, которые Underscore.js пытается решить как внешнюю библиотеку.
Первая проблема заключается в том, что многие примитивы, представленные функциональными языками , такими как map, filter и Reduce, отсутствуют в спецификациях ECMAScript.
Более того, хотя было бы неплохо представить их в единую библиотеку, мы не хотим вторгаться в глобальное пространство имен или даже в базовые объекты, такие как Array , изменяя их прототипы, добавляя удобные функции, такие как Array.map (). В случае, если мы нацелены на функциональный подход, нам даже не нужно присоединять функции к прототипам, поскольку они могут оставаться отдельным пространством имен.
Underscore.js является автономным и не имеет внешних зависимостей; он предоставляет каждую встроенную функцию как часть глобального объекта _ (например, _.map ()). Отсюда следует, что конфликт с другими библиотеками и существующими структурами данных, на которые опирается ваш код, минимален, однако накладные расходы на вызов этих функций составляют несколько символов написания _.
Примеры
Вот отдельная HTML-страница, которая использует Underscore.js для выполнения некоторых простых вычислений с целью показать вам реализацию некоторых популярных функциональных примитивов, таких как map и lower.
Эта страница также зависит от jQuery для удобного отображения результатов, но Underscore.js можно использовать отдельно или в сочетании с другими платформами. Обратите внимание, что на этой странице я удаленно загружаю исходные файлы JavaScript в их версии для разработки, чтобы упростить пример.
<html>
<head>
<script src="http://code.jquery.com/jquery-1.7.2.js"></script>
<script src="http://underscorejs.org/underscore.js"></script>
<script type="text/javascript">
$(function() {
var primeNumbers = [2, 3, 5, 7, 11];
var listIn = function(selector) {
return function(num){
$(selector).append('<p>' + num + '</p>');
};
}
_.each(primeNumbers, listIn('#primenumbers'));
var square = function(num) { return num * num; };
_.each(_.map(primeNumbers, square), listIn('#theirsquares'));
var sum = function(a, b) { return a + b; };
var listInSum = listIn('#sum');
listInSum(_.reduce(primeNumbers, sum, 0));
var even = function(num) { return num % 2 == 0; };
_.each(_.filter(primeNumbers, even), listIn('#even'));
var odd = function(num) { return !even(num); };
listIn('#allodd')(_.all(primeNumbers, odd));
});
</script>
</head>
<body>
<div id="primenumbers">Prime numbers</div>
<div id="theirsquares">Their squares</div>
<div id="sum">Their sum</div>
<div id="even">The even ones</div>
<div id="allodd">Are all primes odd?</div>
</body>
</html>
каждый из них является примитивом, вызывающим функцию для каждого элемента коллекции (большинство этих примитивов работают как с массивами, так и с объектами).
Карта и сокращение , ставшие популярными благодаря алгоритму Google, репрезентативно собирают результаты каждого в новую коллекцию и объединяют элементы коллекции в одно значение.
Другой очень известная функциональная операция является самоописываемым фильтром , но есть очень много примитивов , включенных в Underscore.js, как все , любой , отвергает , и найти . В случае массивов, которые эквивалентны спискам в JavaScript, есть также классические first , rest , zip и так далее.
Еще…
Существует много синтаксических помех в кодировании в функциональном стиле в JavaScript: это язык, который мало разделяет с семейством LISP. Например, отсутствует поддержка автоматического каррирования или отложенной оценки структур данных. JavaScripts не полагается на ссылочную прозрачность, как настоящие функциональные языки, такие как Clojure.
Другая проблема заключается в эффективности, так как это происходит каждый раз, когда вы включаете внешнюю библиотеку для базовых операций, таких как манипулирование массивами. Для решения этой проблемы Underscore.js делегирует собственные функции там, где они доступны: в этом случае основные операции, подобные каждой, будут скомпилированы в самом браузере. В любом случае вам не нужно проверять, поддерживает ли браузер ту функцию, которую вы хотите.
Ресурсы
Чтобы узнать больше о функциональных концепциях и их применении к JavaScript, см. Эту классическую статью на IBM developerWorks .
JavaScript более высокого порядка поможет вам в реализации функциональных примитивов и включает расширенные примеры кода.
Если вы хотите начать использовать Underscore.js, прочитайте аннотированный исходный код в качестве основной формы документации (которая в любом случае генерируется из этого). Иногда стоит заглянуть в примитива, которого вы не знаете, как позвонить, чтобы действительно увидеть, что происходит.