4

After I asked this question and realized that Backbone.Collections are strictly for Backbone.Models, I'm a little disappointed.

What I was hoping for:

Make underscore's methods more object oriented:

_.invoke(myCollection, 'method');  ==>  myCollection.invoke('method');

I'll admit, minor difference, yet still it seems nice.

What problems will I run into if I use Backbone.Collection for non-Backbone.Models?

Are there any existing implementations, or a simple way to make a generic underscore collection class?

Community
  • 1
  • 1
Michael Lewis
  • 4,252
  • 6
  • 28
  • 39
  • 2
    Have you looked at how Underscore methods are mixed into Backbone collections? This is [pretty simple stuff](https://github.com/jashkenas/backbone/blob/master/backbone.js#L941). And Underscore supports a more OO-style (as was explained by meagar): `_(myCollection).invoke('method')`; I use that style almost exclusively. – mu is too short Oct 30 '13 at 23:00
  • From your other questions, if you do `model.views = _([]);`, you then `model.views.push(...)` whatever you want to add to the collection. It's just an array, and the underscore wrapper handles the array methods like you'd expect. – Evan Davis Oct 30 '13 at 23:04
  • @muistooshort: would you store the wrapped `_(myCollection)` or unwrapped `myCollection`? The way Mathletics suggests creating an empty `_([])` seems like a decent approach, then you don't have to wrap it every time. I guess I was really just hoping for a generic class that you could extend from. Maybe I'll look into how Backbone does it, and create my own Generic Collection :). Until then, either of you feel free to answer for points. – Michael Lewis Oct 30 '13 at 23:18

1 Answers1

1

While you can't use a Backbone Collection without using models, I came up with a clever way to mix in underscore into the Array prototype:

// This self-executing function pulls all the functions in the _ object and sticks them
// into the Array.prototype
(function () {
    var mapUnderscoreProperty = function (prp) {
        // This is a new function that uses underscore on the current array object
        Array.prototype[prp] = function () {
            // It builds an argument array to call with here
            var argumentsArray = [this];
            for (var i = 0; i < arguments.length; ++i) {
                argumentsArray.push(arguments[i]);
            }

            // Important to note: This strips the ability to rebind the context
            // of the underscore call
            return _[prp].apply(undefined, argumentsArray);
        };
    };

    // Loops over all properties in _, and adds the functions to the Array prototype
    for (var prop in _) {
        if (_.isFunction(_[prop])) {
            mapUnderscoreProperty(prop);
        }
    }
})();

Here is an example of how to use the new Array prototypes:

var test = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

console.log(test.filter(function (item) {
    return item > 2 && item < 7;
})); // Logs [3, 4, 5, 6]
console.log(test); // Logs the entire array unchanged

This solution might add more to the Array prototype than is actually useful, but it gets you the bulk of the functions. Another solution would be to only add functions that have an iterator argument, but this is a start for you.

DomenicDatti
  • 655
  • 7
  • 15