Move where() from Backbone to Underscore #648

ghostwords opened this Issue Jun 21, 2012 · 12 comments


None yet
7 participants

Backbone's where is very useful. Should it be moved to Underscore (and proxied the usual way back to Backbone)?

The backstory is me trying to use where with chain on a Backbone collection and at first thinking chain is broken.


braddunbar commented Jun 22, 2012

+1 - In my experience, many uses of filter could be written very nicely with where. However, it can't be used in Backbone the same way as other functions since it will need to pull attribute values instead of properties (the same reason pluck is re-implemented).

_.filter(list, function(o) { return o.key === value; });
_.where(list, {key: value});

jashkenas commented Jun 22, 2012

I'm a little bit iffy on it as a general Underscore method because it's only useful on the set of cases where you have arrays of objects with meaningful top-level keys and values. Whereas this is always the case with Backbone collections, the other Underscore methods (pluck aside) don't depend on this being true. Things like map, filter, find, reduce are perfectly useful on arrays of numbers, strings, etc. Do you think it's worth adding where, with this limitation in mind?

I see. The more limited improvement is to have where work with chain in Backbone. The fact that it doesn't work because where is Backbone-only is irrelevant to the end-user.

But re original proposal: Why have pluck and not where in Underscore?

But re original proposal: Why have pluck and not where in Underscore?

That's my thinking as well


It's only useful on the set of cases where you have arrays of objects with meaningful top-level keys and values

For me, this happens all the time when transforming JSON objects from one source to another. I've been mixing in a similar function and I think the #where method in Backbone is a better version of the same thing. I was surprised when I saw it that it hadn't already been pushed up into Underscore.

I think this would be useful even with this limitation. It may be possible to remove this limitation if the argument was treated similar to a zipper as in:

_.filter(list, function(o) { return o.sub.key === value; });
_.where(list, {sub: {key: value}});

The down side is that makes for more complicated code within where.


braddunbar commented Jul 19, 2012

FYI, a request for where from @remy.

+1 - useful enough IMHO to include it.

@jashkenas jashkenas closed this in 5fd4f4e Sep 18, 2012


jashkenas commented Sep 18, 2012

Added. @braddunbar -- if you see any adjustments we need to make to the implementation in order to make it easier for Backbone to proxy over to it later on ... now would be a good time.


braddunbar commented Sep 19, 2012

Unfortunately, I think they're probably best kept separate. I haven't been able to think of a way to shoehorn in support for attributes/get.

I upgraded to Backbone 0.9.10 and Underscore 1.4.3.

Unfortunately, using where with chain on a Backbone collection is still broken. In the example below, filter works, but where does not.

someCollection.chain().filter(function (item) { return !item.get('selected'); }).value()
[...] // works
someCollection.chain().where({ selected: false }).value()
[] // fails

Both work fine when not using chain:

someCollection.filter(function (item) { return !item.get('selected'); })
[...] // works
someCollection.where({ selected: false })
[...] // works

I submit this is unexpected/counterintuitive.

Another case that caught me by surprise: A once-filtered collection (with where, let's say) cannot be further filtered with where (probably since the result of the first filtering is no longer a collection). Using filter works, however:

var visible = someCollection.where({ hidden: false });
// some time later
var visibleAndSelected = _.filter(filtered, function (item) { return item.get('selected'); });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment