什么是Array.map(Function.call,Number)

wil*_*007 10 javascript

var array1 = [1, 4, 9, 16];

map1=array1.map(Function.call,Number);
Run Code Online (Sandbox Code Playgroud)

为什么map1的输出是[0,1,2,3],这个map函数在做什么?

zzz*_*Bov 12

Array.prototype.map 调用为数组的每个成员提供的函数,并返回其返回值的新数组.

在这种情况下,提供的功能是Function.call.

第二个参数Array.prototype.map指定应运行提供的函数的上下文.

在这种情况下,上下文是Number.

一个天真的实现Array.prototype.map可能看起来像是:

function map(callback, thisArg) {
  const ret = []
  for (let index = 0; index < this.length; index++) {
    const value = this[index]
    ret.push(callback.call(thisArg, value, index, this))
  }
  return ret
}
Run Code Online (Sandbox Code Playgroud)

现在,这个特殊的情况使用了大量的间接,因此不容易看出为什么传递Function.call并且Number应该返回[0, 1, 2, 3],所以让我们来看看那个部分.

当在callback(Function.call)的上下文中调用thisArg(Number)时,代码将执行以下行:

(Function.call).call((Number), (1), (0), ([1, 4, 9, 16]))
//   ^-- callback               ^-- value ^-- array
//                    ^-- thisArg    ^-- index
Run Code Online (Sandbox Code Playgroud)

评估Function.call.call(...)有点令人费解,但它相当于call在第一个参数的上下文中调用函数,该参数应该是一个函数.在我们的例子中,它是.这是Number功能.

然后我们可以将此语句简化为:

Number.call(1, 0, [1, 4, 9, 16])
Run Code Online (Sandbox Code Playgroud)

该Number函数将第一个参数转换为数字.忽略其他参数以及函数上下文.这意味着整个表达式可以简化为:

Number(0)
Run Code Online (Sandbox Code Playgroud)

这里0是index.

这就是返回值的原因[0, 1, 2, 3],因为它们是原始数组的索引.


不言而喻,原始代码示例不应该用于日常编程.整个系统使用起来会更简单:

[1, 4, 9, 16].map((value, index) => index)
Run Code Online (Sandbox Code Playgroud)

即使这样,也应该注意到原始价值被无用地抛弃了.此类代码示例仅在探索特定语言行为的学术意义上有用,或者当您想要将您的朋友故意混淆为编码挑战的一部分时.


Jos*_*bou 5

在此处阅读Array#map的用法

输入参数为 map(callback, this)

在您的示例中,您将提供函数Function.call作为映射器,它是的构造函数Function。函数是说“运行此函数”的一种基本方法,而this您要绑定的是给它第一个arg。

有趣的地方是您给它的回调函数使用了args (currentValue, index)。通过传递Function.call并将其绑定,实际上是在强迫它删除第一个arg。这是一种使“ Number”函数在索引上运行的聪明方法(阅读:难以理解)。

例如try [1, 4, 9, 16].map(Function.call, String),你会看到同样的东西,但是解析为字符串["1", "4", "9", "16"]。

让我们逐步了解一下第一次迭代时发生的情况,以更加清楚:

  • Function.call调用回调函数,传递args 1(当前值)和0(当前索引)
  • 该回调Number在执行之前绑定到第二个arg ,因此就像调用Function.call.bind(Number)(1, 0)
  • 第一个参数Function.call说“绑定到此上下文”,但是bind上面的显式调用将覆盖此参数
  • 实际运行的是Number(0),当然0是索引。

如今,我认为大多数人会简单地将箭头函数与他们可以忽略的第一个arg一起使用,例如array1.map((_, i) => Number(i))(或者更好的是Number.parseInt,如果要获取整数)。

虽然作为一名软件开发人员,整个过程非常酷,但是我不建议map(Function.call)在实践中使用这种模式!如果您在自己的代码中遇到过它,至少要添加一条注释,这样下一个开发人员就不必来了:)