Liam told me about Underscore.js some time ago. From the home page:
Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects. It's the tie to go along with jQuery's tux.
The functional programming support from Underscore includes, but is not limited to, the standard map, filter, reduce functionality.
var data = [1, 2, 3, 4, 5, 6, 7, 8, 9]; var result = _.filter(data, function (n) { return n % 2 == 0; }) .map(function (n) { return n * n; }) .reduce(function (sum, n) { return sum += n; });
Notice the gateway to all the Underscore features is the _ (underscore) object.
What I've found useful recently are the throttle and debounce methods. Throttle ensures a method is only called once every n milliseconds, while debounce will ensure a method is only called after someone stops calling the method for n milliseconds. I'm fond of debounce because I spent many hours years ago writing debounce logic for mechanical switches, but also because it demonstrates the power of composing behavior with higher order functions. Both throttle and debounce use an internal function called limit to implement their behavior (the source code from Underscore shown below, sans comments).
var limit = function (func, wait, debounce) { var timeout; return function () { var context = this, args = arguments; var throttler = function () { timeout = null; func.apply(context, args); }; if (debounce) clearTimeout(timeout); if (debounce || !timeout) timeout = setTimeout(throttler, wait); }; }; _.throttle = function (func, wait) { return limit(func, wait, false); }; _.debounce = function (func, wait) { return limit(func, wait, true); };
There are so many interesting concepts in the limit function – I think you could build an 8 hour workshop from those 11 lines of code.
To see how throttle would work, you could use the following code to process and log mouse movement, but throttle the processing so you only see the console output once every 1,000 milliseconds.
$(window).mousemove(_.throttle(function (e) {
console.log(e.pageX, e.pageY);
}, 1000));
Fantastico!