25

A common pattern within jQuery is a method that takes a callback which is passed an element of an array and its index within that array. However, it seems completely random which argument comes first. For example, from the jQuery docs at http://api.jquery.com:

  • jQuery.each( collection, callback(indexInArray, valueOfElement) )
  • .each( function(index, Element) )
  • jQuery.map( array, callback(elementOfArray, indexInArray) )
  • .map( callback(index, domElement) )
  • jQuery.grep( array, function(elementOfArray, indexInArray), [ invert ] )
  • .filter( function(index) )

In three cases (jQuery.each, .each, .map) the index comes first. In the other two (jQuery.grep, jQuery.map) the element comes first. I know the api is now set, but it seems like a gross inconsistency to me.

Is there a pattern I'm missing or is this just random? Should this be fixed or should I just shut up and memorize them?

brad
  • 73,826
  • 21
  • 73
  • 85

4 Answers4

8

It is not totally random. Because :

$.map( $('selector'), function(el, index) { /* element (DOMElement) is first, index optional */ } );
$('selector').map(function(index) { /* 'this' (DOMElement) is first.... index optional */ });

See the pattern? The second example has a second argument, but it is only passed by convenience, and it is the same as this.

The pattern is that the first argument is always "more" important than the second, and the last argument should be the least important (the "more optional"). So you don't need to specify all the least important arguments if you only need one. And in the case of $(...).each, often you won't even need any argument, because this is only what you want.

Yanick Rochon
  • 51,409
  • 25
  • 133
  • 214
  • 2
    same thing with selectors and context. $(myselector,mycontext) context is optional which is why it is second. – Mark Schultheiss Aug 31 '10 at 19:16
  • Makes sense - nice point! I was starting to get annoyed, but now if I think of it like this I'll probably be able to remember! – Jason Aug 26 '12 at 22:03
  • 3
    This doesn't really answer anything - index is more important than element in some cases, but not others? And "this" is not consistently the same as first parameter. For example: `$ ("selector").each(function(index, el) { // el === this } )` – pimlottc Oct 31 '13 at 18:10
  • @pimlottc, yes, since `$(...).each(function(i, el) {...})` binds the current element as `this` inside the callback, the index `i` becomes, thus, more important than the element `el` as paramters. Whereas `$.each( $(...), function(el, i) {...})`, the arguments are inverted since `this` is now `window`, thus makes `el` more important and `i` less. Pretty simple, no? – Yanick Rochon Oct 31 '13 at 19:34
  • 2
    @YanickRochon I don't consider this to be "simple" by any simple definition of the word "simple". How is it any better that we also have to remember which *specific* methods bind something useful to `this` (let alone what that item is)?? – Steven Lu Nov 23 '14 at 00:12
7

That's frustrated me also at times -- $.each is the one that I always mess up.

I think it's due to different people/teams working on different parts of the framework. It's a community-driven framework, so nobody probably caught it early on and now that the framework is so wide-spread, they can't fix it without breaking 35% of all the sites on the Internet.

I don't think it will be fixed -- at least that's my opinion/attitude. I'm just going to have to commit them to memory and hope for the best!

David Hoerster
  • 28,421
  • 8
  • 67
  • 102
2

Since Javascript lets you ignore parameters that you aren't using (i.e., you can define a callback function which takes only one parameter, even if it will be called with two), generally, the first parameter is the one you are mostly likely to be using. (Actually, the this varaible is usually the data item you'r most likely to use, followed by the first parameter, etc)

James Curran
  • 101,701
  • 37
  • 181
  • 258
2

According to https://learn.jquery.com/using-jquery-core/iterating/

A word of warning: $.map() switches the order of callback arguments [when compared to $().map, $each() and $().each()]. This was done in order to match the native JavaScript .map() method made available in ECMAScript 5.

kbro
  • 4,754
  • 7
  • 29
  • 40