开发者

jQuery $.map vs $.fn.map different arguments

I'm just wondering if anyone knows why $.map and $.fn.map pass arguments in flipped order from one-another. Is there a valid reason (e.g. ECMA specs somewhere) for it or was it just a poorly-planned API that is 开发者_如何学运维now impossible to fix due to the amount of code relying on jQuery?

$.map([ 'a', 'b', 'c' ], function(){ console.log(arguments); })
// ['a', 0], ['b', 1], ['c', 2]

$.fn.map.call([ 'a', 'b', 'c' ], function(){ console.log(arguments); })
// [0, 'a'], [1, 'b'], [2, 'c']

.each doesn't act like this


Indeed, that might be considered as an oversight, but there is a very good reason for the arguments to be passed in that order.

Of course, on the surface, that's because the map() / each() methods and $.map() are not supposed to be equivalent, and each side is meant to be used in its own way (dealing with jQuery objects and arrays/hashes, respectively).

But the main point is that the parameter position is optimized for the case your callback function only wants to take a single argument. Consider both cases:

  • map() and each() are meant to be called on jQuery objects, and the callback function will be called in the context of each DOM element involved in the mapping/loop (the context object is available through the this keyword). So, it makes more sense to pass the index first, then the element, because this already designates the element.

  • $.map() deals with arrays and Javascript objects (hashes), and the callback function is invoked in the "global" context (this is always the window object). So, it makes more sense to pass the value first, then the index, because mapping is about avoiding loop index variables in the first place. If the caller is interested in those, he can use a "standard" for loop (or the second argument passed to the callback function).


Here's my completely and entirely speculative "answer".

jQuery.each(), .each() and jQuery.map() were all present in version 1.

.map() was added in 1.2.

My guess is that they simply didn't give consideration to having the each methods follow the forEach in the spec. (What was the status of ES 5 at that time anyway?) But for some reason they did follow closer to the spec for $.map(). (Maybe its original intention was for primarily internal use as well.)

So when jQuery 1.2 came along, they decided it would be nice to have a .map() method.

So the question they faced was to have .map() follow $.each() and .each(), or follow $.map().

Since .each() in particular had already been implemented as callable against a jQuery object, they felt that it would cause less confusion to have .map() follow .each() than to follow $.map(), which is most certainly not used as much.

Looking at the source for the .map() method vs the .each() method, you can see that .map() requires an intermediate function in order to flip around the arguments and set the this value. Somehow I doubt that they would have wanted to do that if they had it all planned out in advance.

Again, this is complete and utter speculation, but I wouldn't be surprised if it happened something like that.

Take it or leave it. ;o)


Ok, I did some digging in the code and the API changelog.

$.fn.map internally calls jQuery.map.

Its a guess (somewhat calculated) but I believe it was done to add the ability to traverse objects/collections.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜