.map.call in Javascript

Hi I recently looked at some code and the only part I don’t understand and know how to use is .map.call part. Could anyone explain what it means and how to use.

below is the code it has been used in;

function rot13(str) {
  // Split str into a character array
  return str.split('')
  // ###########################
    .map.call(str, function(d) {
      // Convert char to a character code
      x = d.charCodeAt(0);
      // Checks if character lies between A-Z
      if (x < 65 || x > 90) {
        return String.fromCharCode(x);  // Return un-converted character
      }
      //N = ASCII 78, if the character code is less than 78, shift forward 13 places
      else if (x < 78) {
        return String.fromCharCode(x + 13);
      }
      // Otherwise shift the character 13 places backward
      return String.fromCharCode(x - 13);
    }).join('');  // Rejoin the array into a string
}

// Change the inputs below to test
rot13("SERR PBQR PNZC");

Both of these seem to end up with the same result:

return str.split('').map.call(str, function(d) {

and

return str.split('').map(function(d) {

Normally map.call allows you to work with the individual characters of that string without splitting it first. That is already happening in this case though, so the .call seems to be superfluous.

str is the string that is to be processed.
the string split method splits the string into an array of individual characters
the array map method processes every entry in the array and replaces each value with whatever the callback function returns
the function call method allows us to substitute a different object for the one the preceding function call expects - in this case to substitute the original str value for the array of individual characters - but since the function never references the str field it is superfluous
the array join method then joins the updated array back together into a string to return from the function

Correction - the str value replaces the str.split array, resulting in .map instead processing the characters from str.

var result = "Unexpected".split("").map.call("Expected", function (char) {
    return char.toUpperCase();
}).join("");
// result ends up being "EXPECTED"

When map.call is being used, str.split(“”).map ends up being a disguised way of calling Array.prototype.map instead.

For reference, see the Calling Map Generically section at the Array.prototype.map() page, which uses the following example code:

var map = Array.prototype.map;
var a = map.call('Hello World', function(x) { return x.charCodeAt(0); });
// a now equals [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]

You’re right that it does that but that doesn’t change that the following version of the function gives exactly the same result without needing the call step making the call superfluous in this particular function…

function rot13(str) {
  return str.split('').map(function(d) {
      x = d.charCodeAt(0);
      if (x < 65 || x > 90) {
        return String.fromCharCode(x);
      }
      else if (x < 78) {
        return String.fromCharCode(x + 13);
      }
      return String.fromCharCode(x - 13);
    }).join('');
}

or for a shorter version:

function rot13(str) {
  return str.split('').map(function(d) {
      x = d.charCodeAt(0);
      if (x < 65 || x > 90) {
        return String.fromCharCode(x);
      }
      return String.fromCharCode(((x-52)%26)+65);
    }).join('');
}

Yes indeed, both of the following have exactly the same end result:

str.split("").map(...
Array.prototype.map.call(str, ...

Given a choice between the two, the former in this case is the better option as its easier to understand what is going on.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.