Книга: Functional Programming in JavaScript
Назад: Lenses
Дальше: Implementing categories

jQuery is a monad

If you think all this abstract babble about categories, functors, and monads has no real-world application, think again. jQuery, the popular JavaScript library that provides an enhanced interface for working with HTML is, in-fact, a monadic library.

The object is a monad and its methods are functors. Really, they're a special type of functor called endofunctors. Endofunctors are functors that return the same category as the input, that is, . Each method takes a object and returns a object, which allows methods to be chained, and they will have the type signature .

$('li').add('p.me-too').css('color', 'red').attr({id:'foo'});

This is also what empowers jQuery's plugin framework. If the plugin takes a object as input and returns one as output, then it can be inserted into the chain.

Let's look at how jQuery was able to implement this.

Monads are the containers that the functors "reach into" to get the data. In this way, the data can be protected and controlled by the library. jQuery provides access to the underlying data, a wrapped set of HTML elements, via its many methods.

The object itself is written as the result of an anonymous function call.

var jQuery = (function () {   var j = function (selector, context) {     var jq-obj = new j.fn.init(selector, context);     return jq-obj;   };    j.fn = j.prototype = {     init: function (selector, context) {       if (!selector) {         return this;       }     }   };   j.fn.init.prototype = j.fn;   return j; })();

In this highly simplified version of jQuery, it returns a function that defines the object, which is actually just an enhanced constructor.

var $ = jQuery(); // the function is returned and assigned to `$` var x = $('#select-me'); // jQuery object is returned

In the same way that functors lift values out of a container, jQuery wraps the HTML elements and provides access to them as opposed to modifying the HTML elements directly.

jQuery doesn't advertise this often, but it has its own method for lifting the HTML element objects out of the wrapper. Just like the method, the elements are lifted, something is done with them, and then they're placed back into the container. This is how many of jQuery's commands work in the backend.

$('li').map(function(index, element) {   // do something to the element   return element });

Another library for working with HTML elements, Prototype, does not work like this. Prototype alters the HTML elements directly via helpers. Consequently, it has not faired as well in the JavaScript community.

Назад: Lenses
Дальше: Implementing categories

bsn
thank
Vesa Karvonen
I hope you don't mind, but I’d like to point you and your readers to my high-performance optics library for JavaScript that is in production use in multiple projects, has comprehensive support for partial optics and interactive documentation: https://calmm-js.github.io/partial.lenses/ (this takes a moment to load — be patient!)