Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array.prototype.map is not a function when passing a function generated by Function.prototype.call as argument

Sometimes I use the Array.prototype.map methode like so :

var array = ['1', '2', '3', '4'].map(parseFloat); // the result is [1, 2, 3, 4]

parseInt takes 2 arguments it returns incorrect values in this case

Now what I'm trying to do is instead of this code :

var  array = ['a', 'b', 'c', 'd'].map( function (item) { 
    return item.toUpperCase(); 
}); // the result is ['A', B', 'C', 'D']

I tried this :

var array = ['a', 'b', 'c', 'd'].map(''.toUpperCase.call);

can someone explain to me why I get an error that says :

Uncaught TypeError: ["a","b","c","d"].map is not a function

like image 674
Khalid Avatar asked Jun 02 '15 11:06

Khalid


1 Answers

The first problem is you pass the function ''.toUpperCase.apply which is the same as Function.prototype.apply: it isn't bound.

What happens is equivalent to

['a', 'b', 'c', 'd'].map(function(v, i, arr){
   return undefined.apply(v, i, arr)
});

If you bind it using

['a', 'b', 'c', 'd'].map(''.toUpperCase.apply.bind(''.toUpperCase));

then you have a second problem: map doesn't pass only one parameter to your callback. It also pass the index and the whole array.

You could "fix" the two problems with

['a', 'b', 'c', 'd'].map(function(v){ return ''.toUpperCase.apply(v) });

(more an explanation than a fix, right)

Using call is easier and can be fixed:

var arr = ['a', 'b', 'c', 'd'].map(''.toUpperCase.call.bind(''.toUpperCase));

which should be written as

var arr = ['a', 'b', 'c', 'd'].map(Function.prototype.call.bind(''.toUpperCase));

Side note: you were lucky to use parseFloat in the first example. Try with parseInt.

like image 112
Denys Séguret Avatar answered Sep 24 '22 12:09

Denys Séguret