Reputation: 4808
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
Upvotes: 5
Views: 21004
Reputation: 382150
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
.
Upvotes: 4
Reputation: 59232
When you pass ''.toUpperCase.call
to Array.map
, though it will pass the argument correctly, the call
function disintegrates from toUpperCase
function, which holds the implementation details.
So, now the Function.call
does have the correct argument passed to it by the Array.map
callback function, but it holds no reference to ''.toUpperCase
function.
MDN: You can assign a different
this
object when calling an existing function.this
refers to the current object, the calling object.
So ''.toUpperCase.call("a")
is entirely different to call("a")
, which is what is happening when you pass ''.toUpperCase.call
to Array.map
Upvotes: 1