Working on a new project, with both jQuery and Underscore.js, I found myself with a problem. Using Underscore.js on jQuery objects felt somewhat dirty/messy:
// With $ and _ both in scope...
// Typical code:
_($('.someclass'))
.each(function(element) {
element = $(element);
// Run some jQuery on 'element'.
});
_.chain($('.someclass'))
.filter(function(element) {
element = $(element);
// Test some jQuery on 'element'.
})
.each(function(element) {
element = $(element);
// Run some jQuery on 'element'.
});
The two key problems I had were:
- The initial "_($('..." and "_.chain($('..." bugged my sense of clean code.
- I had to re-wrap every element in jQuery inside each filter() or each() or any other Underscore.js iterator function.
The solution I found is pretty simple and also in two parts:
- Add a new mix-in to Underscore.js: the jQuery $() function.
- Use the map() method from Underscore.js directly with jQuery's $() function. (This also meant an increased use of the chain() method.)
// With $ and _ both in scope...
// One-time set-up:
_.mixin({$: $});
// Typical code:
_.chain('.someclass')
.$() // This uses jQuery to select the elements matching the selector.
.map($) // This uses Underscore.js to wrap every matched element in jQuery.
.filter(function(element) {
// Test some jQuery on 'element'.
})
.each(function(element) {
// Run some jQuery on 'element'.
});
Much cleaner!
Addendum: It was pointed out to me that you can avoid the chain() methods of Underscore.js by replacing that library with Lo-Dash, which has much the same API, but with better performance and more intuitive method chaining (i.e. more like jQuery). Thanks tom!