4

Out of curiosity:

The MDN taught me how to shortcut function application like this:

trim = Function.prototype.call.bind(String.prototype.trim)

join = Function.prototype.call.bind(Array.prototype.join)

Now, I can map trim, but not join for some reason. join takes ',' as default argument (separator), so I should be fine, but instead it uses the array index:

> trim = Function.prototype.call.bind(String.prototype.trim)
call()
> [' a','b '].map(trim)
["a", "b"]
> join = Function.prototype.call.bind(Array.prototype.join)
call()
> [['a','b'],['c','d']].map(join)
["a0b", "c1d"]

Why?

Also, what if I actually wanted a different separator? Passing it to bind doesn't work, since it is prepended to the existing arguments (at any time one of the elements of the list on which I map). Then it takes the role of the strings to join and the strings to join would act as separators if there was something to separate:

> joins = Function.prototype.call.bind(Array.prototype.join,';')
call()
> [['a','b'],['c','d']].map(joins)
[";", ";"]

I have researched and found:

Answers explaining the thing with this and solutions equivalent to the bind shortcut I referenced

Similar explanations, the solution using thisArg again, from MDN's page about map

A duplicate question with duplicate answers

Community
  • 1
  • 1
Leif Willerts
  • 205
  • 1
  • 9
  • 1
    This answers the "Why?": https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Example:_Tricky_use_case – Paul Jul 21 '15 at 21:00
  • Well, `trim` does ignore the arguments it's passed, `join` *doesn't*. – Bergi Jul 21 '15 at 21:34

1 Answers1

2

The function you pass into map receives 3 arguments. Basically map works like this.

Array.prototype.map = function(f) {
  var result = [];
  for(var i = 0; i < this.length; i++) {
    result.push(f(this[i], i, this));
  }
  return result;
}

So when you run this code [['a','b'],['c','d']].map(join), this is what's happening inside map

join(['a', 'b'], 0, [['a','b'],['c','d']])
join(['c', 'd'], 1, [['a','b'],['c','d']])

To get the result you want you could write a function that can generate join functions. e.g.

function joinSep(separator) {
  return function(array) {
    return array.join(separator)
  }
}
var joins = joinSep(';');
[['a','b'],['c','d']].map(joins)
Tesseract
  • 8,049
  • 2
  • 20
  • 37