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, прочитайте аннотированный исходный код в качестве основной формы документации (которая в любом случае генерируется из этого). Иногда стоит заглянуть в примитива, которого вы не знаете, как позвонить, чтобы действительно увидеть, что происходит.