Array.prototype.map is not a function when passing

2020-07-13 07:23发布

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

2条回答
Ridiculous、
2楼-- · 2020-07-13 07:42

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.

查看更多
欢心
3楼-- · 2020-07-13 07:51

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

查看更多
登录 后发表回答