A peek into JavaScript’s Array.prototype.map and jQuery.map


The map function comes from JavaScript’s functional programming roots: it applies a function to every array element and returns a new array of the results without mutating the original array. So lets look at the native JS and jQuery map implementations.

Array.prototype.map

The signature for the native JS implementation is:

array.map(callback, thisObject)

The callback is the transforming function that changes elements of array into new elements while thisObject will be this inside the callback (some cool applications exist). Most browsers allow Array.protototype.map  (support got added in JavaScript 1.6) however a few browsers still do not.

jQuery’s map

The signature for the jQuery implementation is:

$.map(array, callback, arg)

The array and callback parameters mean the same as above while the arg parameter allows you to send in extra arguments into the function ( I still haven’t found a use for this yet).  Unfortunately this inside the callback refers to the Global object (Window); if you need to get around this, you can wrap the callback in a $.proxy  call.

What’s the Callback?

The callback function is triadic in both implementations; the three parameters being the array element, the element’s index and the entire array (why this is needed still puzzles me).

jQuery callback example

var numbers = [1,2,3,4],
 squareNumbers = function (number) {
     return number * number;
 },
 squares = $.map(numbers, squareNumbers);

console.log(squares);//logs [1,4,9,16]

Array.prototype.map callback example

var numbers = [1,2,3,4],
    squares = numbers.map(squareNumbers);

console.log(squares);//logs [1,4,9,16]

Using element indices

If the element indices matter to you, take it into consideration the subtle differences between both implementations.

jQuery example

The jQuery’s map method will always return a flattened array which does not contain null/undefined values.

var numbers = [1,2,3,4],
    getAllEvenIndices = function(number, indexInArray){
        if(indexInArray % 2 === 0) return number
    },
    evenIndexedNumbers = $.map(numbers, getAllEvenIndices);

console.log(evenIndexedNumbers); //logs [1,3]

Native JS map example

The native implementation does not filter out undefined values.

var numbers = [1,2,3,4],
    evenIndexedNumbers = numbers.map(getAllEvenIndices);

console.log(evenIndexedNumbers);
//logs [1, undefined, 3, undefined]

Can I use Objects?

Surprisingly yes! You can call the jQuery.Map function on an object, for example, you have a JSON payload coming in from the server and you want an array of the values or keys, it is simple and easy to do this:

var payload = { id : 1, username : "xyz", points : 10}
    retrieveKeys = function (value, key) {
        return key;
    },
    payloadKeys = $.map(payload, retrieveKeys);

console.log(payloadKeys);//logs ["id", "username", "points"]

I don’t know of any simple way to do this using the native JS Array.prototype.map (I don’t know if it is even possible, maybe with some JS kung-fu. :) ).

So why use jQuery’s array.map if the JS language supports it implicitly? Here are a couple of reasons: the jQuery version strips off both undefined and null values, will work fine in all browsers (IE7 + IE8 do not have native support). But you can always write a polyfill too…

Here’s a puzzler: what would the snippet below return?

var result = $.map ([[1,2], [3,6]], function(elem) {
    return elem;
})

Did you enjoy this post? Check out my other posts on JS, JS Events and JS functional Programing.

5 Comments

·

Leave a Reply

  1. As always Abdul, well done!

    Re: Using nativeJS to get the keys with Kung Fo
    there’s actually a method for that but it only works in the more recent/modern browsers –

     var payloadKeys = Object.keys(payload);
    

    Only makes sense to use this if you’re absolutely sure only modern browsers will be used (ideal and kinda rare). Otherwise, let jQuery do the work for you even when Object.keys() not supported by the browser.

    Like

    • Thanks a lot Oga Femi! Thanks for the motivation! :) It’s a honour to have you read my posts!

      Aah, my write-up wasn’t clear enough (I should update it) – I was wondering if it was possible to use the Array.prototype.map method on Objects. Something along the lines of Array.prototype.map.bind, please do you know if this is possible?

      The Object.Keys method is cool – EcmaScript 5 has lots of goodies :); have you tried the Object.getOwnPropertyNames? I found out that it allows you to iterate over non-enumerable values.

      var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
      
      Object.keys(days);
      //logs ["0", "1", "2", "3", "4", "5", "6"]
      
      Object.getOwnPropertyNames(days);
      //logs ["0", "1", "2", "3", "4", "5", "6", "length"]
      

      Thanks a lot once again!

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s