dojo.map and jQuery.map

January 27th, 2009
wolfram

In one of our current customer’s projects we are working with jQuery. And I am glad that the functional programming basics are already kind of standard across JS libraries. Especially with dojo I started to love the functional approaches and realized that they are really helpful in a lot of situations, especially when doing data processing. One of the best known functions is the map function, which “creates a new array with the results of calling a provided function on every element in this array” [from Mozilla's Core JS References]. Though dojo and jQuery implement this function there are slight differences.

The root of all evil was a simple function that was searching for certain information in some data and returning me a piece of those, it looked like this:

1
2
3
>>> jQuery.map([{id:1}, {id:2}], function(n){return n.id>1 ? n.id : null})
    .filter(function(n){ return n!=null })
[2]

Looks pretty simple, but it failed in IE. There is some problem with the filter() function in IE, it just barks when I run the following

1
2
>>> jQuery.map([1, 2], function(){return null}).filter(function(){})
Object doesn't support this property or method

May be I oversaw some really simple error I made. But anyway, that lead me to debugging this thing and trying stuff out and I discovered that the following happens.

1
2
>>> jQuery.map([1,2,3], function(){return null})
[]

But I was very sure that dojo would return an array of three elements with null each. So I tried that of course.

1
2
>>> dojo.map([1,2,3], function(){return null})
[null, null, null]

Aha, that’s what I expected. So jQuery just does it a little different. Ok, good to know, this again means that I can cut my initial script shorter, by just removing the filter() call. Good thing.

1
2
>>> jQuery.map([{id:1}, {id:2}], function(n){return n.id>1 ? n.id : null})
[2]

So that this works and only returns the id if it is larger than 1, which is actually the case that I need. While I find this quite handy and had wished for it a lot of times in dojo too, I see it as rather inconsistent, simply because it is a special case, you would need to know about.
Since Firefox3 comes with the map() function already implemented (so it must be at least JavaScript 1.6) I tried the native method:

1
2
>>> [1,2,3].map(function(){ return null })
[null, null, null]

And as I expected it does return the elements in the array, just like dojo does.
So note jQuery does it differently. Which is kind of ok, since the map() function is implemented in it’s own namespace and does not override the native map() function but I find it confusing.
And dojo just does it as the map() function which is defined in the JavaScript spec.
Just in case someone else stumbles over it …

Comments

Interesting discovery. I think I like the fact dojo.map matches the spec more than the convenience of being able to return null in the map call to shorthand filter. It could just be an oversight in jQuery though, as following the spec makes more sense. Bug or feature?

1

January 28, 2009 — 05:29 pm
Peter Higgins

By looking at the source via jQuery.map.toString() you can see quickly that it seems intentionally,
http://code.google.com/p/jqueryjs/source/browse/trunk/jquery/src/core.js#1120
As I said, while I understand the reasoning, I agree with you Pete.

2

January 28, 2009 — 05:52 pm
Wolfram Kriesing

duly noted. just noticed also dojo.filter == jQuery.grep … you were trying to .filter() on a native array.

3

January 28, 2009 — 06:19 pm
Peter Higgins

Yes, it seems to be an intentional shortcut to allow you to remove elements from the array map by returning null. I find the shortcut very convenient, because it has worked on everything I’ve needed it so far.

4

March 19, 2009 — 09:33 pm
Marc Grabanski

@Marc yes, it is handy indeed, it is just not as the native JavaScript map function will do it. But I am also one who adapts to using tabs instead of spaces ;-)

5

March 20, 2009 — 01:30 am
Wolfram Kriesing

Also, there is no way to pass a scope-object (this) for the callback to jQuery.map(). You’d have to hitch the callback. But there is no hitch in jQuery. This is so börken.

6

March 10, 2011 — 01:38 pm
kioopi

Leave a Reply