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

时间:2018-05-23 02:29:40

标签: javascript

GetListValues $prm $charCount

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

4 个答案:

答案 0 :(得分:11)

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
}

现在,这个特殊情况使用了很多间接,因此很难理解为什么传递Function.callNumber应该返回[0, 1, 2, 3],所以让我们来看看那部分。

callbackFunction.call)的上下文中调用thisArgNumber)时,代码将按以下方式执行:

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

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

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

Number.call(1, 0, [1, 4, 9, 16])

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

Number(0)

其中0index

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

不言而喻,原始代码示例不应该用于日常编程。整个系统可以更简单地使用:

[1, 4, 9, 16].map((value, index) => index)

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

答案 1 :(得分:4)

阅读Array#map here

的用法

输入参数为map(callback, this)

在您的示例中,您提供了函数Function.call作为映射器,它是Function的构造函数。功能是说&#34;运行此功能的基本方式&#34;,this你的约束是给它第一个arg。

如果它变得有趣,你给它的回调是否需要args (currentValue, index)。通过传递Function.call并绑定它,你实际上强迫它放弃第一个arg。这是一个聪明的(阅读:难以理解)的方式来获得你的&#34;数字&#34;函数在索引上运行。

e.g。试试[1, 4, 9, 16].map(Function.call, String),您会看到相同的内容,但会将其解析为字符串["1", "4", "9", "16"]

让我们逐步了解第一次迭代发生的事情,以便更清晰:

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

如今,我认为大多数人会简单地使用箭头功能,他们可以忽略第一个arg,例如array1.map((_, i) => Number(i))(或者更好,Number.parseInt,如果您正在尝试获取整数。)

虽然作为一名软件开发人员阅读这篇文章非常酷,但我在实践中并不推荐这种map(Function.call)模式!如果你在自己的代码中遇到过它,至少添加一条评论,以便下一个开发者不需要来SO:)

答案 2 :(得分:3)

一些背景

Array.prototype.map有两个参数:第一个是用数组中的每个项调用的函数,第二个很少使用的参数是一个this值,第一个参数被调用。例如:

[1,2,3].map(function() { return this.x; }, {x: 3}) // returns [3,3,3]

Function.prototype.call是一个关于所有函数的函数:(Function本身就是一个函数,因此Function.callFunction.prototype.call),它允许调用函数特定的this和一组特定的参数(单独传递,而不是Function.prototype.apply的数组)。例如:

function someFunction(y) {
    return this + y;
}
someFunction.call(2, 3) // Returns 5, since this=2 and y=3

但真实例子中还有一个额外的细节,因为它没有someFunction.call,它正在做Function.call:它正在发生什么是Function.prototype.call正在使用this来确定调用哪个函数:如果重新绑定this,则会调用另一个函数。您可以使用this重新绑定Function.prototype.call。{/ 1}}。

所以这等同于前面的例子:

function someFunction(y) {
    return this + y;
}
Function.call.call(someFunction, 2, 3)

.call的第二次调用重新绑定第一个,以便它调用someFunction而不是Function,并将参数2和3传递给它:它归结为{{{} 1}},我们已经看过了。

解释

回到真实的例子,我们可以把事情放在一起,我们有

someFunction.call(2, 3)

第二个参数确实绑定,就像[3,6,9].map(Function.call, Number) 一样,所以这相当于:

.call
正如我们刚才看到的那样,等同于更直接的方式:

[3,6,9].map((...args) => Function.call.call(Number, ...args))

那么,现在,[3,6,9].map((...args) => Number.call(...args)) 是什么?对于每个调用,它们都是数组中的项,数组中的位置以及整个数组。所以这真的扩展到:

...args

现在请记住,[ Number.call(3, 0, [3,6,9]), Number.call(6, 1, [3,6,9]), Number.call(9, 2, [3,6,9]) ] 的第一个参数是Number.call,而另外两个参数被提供给被调用的函数this。据我所知,Number并没有使用Number,所以它基本上只是抛出第一个参数,所以它是:

this

[ Number(0, [3,6,9]), Number(1, [3,6,9]), Number(2, [3,6,9]) ] ,只接受一个参数,它会转换为数字。这是微不足道的,尽管它的论点已经是一个数字。这就是你得到Number的方式。它只是索引,不必要地转换为数字,具有很多功能间接。

答案 3 :(得分:0)

Array.map函数创建一个新的Array,其结果是在Array中调用Array.map的每个元素上调用提供的Function(Function.call)。

e.g。

// Store an initial Array of String values
var stringArray = ['Matt','Long','JavaScript'];

// Invoke Function for each value of Array
 mapResult = stringArray.map((currentValue) => {
     // Concatenate and return
    return currentValue + ' Software';
});

// Log map result
console.log(mapResult);

你正在传递号码作为&#39;这个&#39;在为Array中的每个值执行回调时要使用的值。在结果数组中,每个元素都是对Array中每个值调用给定Function的结果。

Function.call方法使用给定的&#39;这个&#39;价值和提供的论据。