将function.prototype.call生成的函数作为参数传递时,Array.prototype.map不是函数

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

本文关键字:函数 prototype Array map 参数传递 call function      更新时间:2023-09-26

有时我使用Array.prototype.map方法,如下所示:

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

parseInt接受2个参数,在这种情况下返回不正确的值

现在我要做的是代替这个代码:

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

我试过这个:

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

有人能向我解释一下为什么我会得到一个错误,上面写着:吗

未捕获类型错误:["a","b","c","d"].map不是函数

第一个问题是传递函数''.toUpperCase.apply,该函数与Function.prototype.apply相同:它没有绑定。

发生的情况相当于

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

如果您使用进行绑定

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

那么您会遇到第二个问题:map不会只向回调传递一个参数。它还传递索引和整个数组。

你可以用"修复"这两个问题

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

(与其说是修复,不如说是解释(

使用call更容易,可以修复:

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

应该写为

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

旁注:您很幸运在第一个示例中使用了parseFloat。尝试使用parseInt

当您将''.toUpperCase.call传递给Array.map时,尽管它会正确地传递参数,但call函数与toUpperCase函数分离,后者保存了实现细节。

因此,现在Function.call确实有Array.map回调函数传递给它的正确参数,但它没有引用''.toUpperCase函数。

MDN:调用现有对象时,可以分配不同的this对象作用this是指当前对象,是调用对象

因此,''.toUpperCase.call("a")call("a")完全不同,这就是当您将''.toUpperCase.call传递给Array.map

时发生的情况