GetListValues $prm $charCount
为什么map1的输出是[0,1,2,3],这个地图函数在做什么?
答案 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.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
评估Function.call.call(...)
有点令人费解,但它相当于在第一个参数的上下文中调用call
函数,该参数应该是一个函数。在我们的例子中,它是。这是Number
函数。
然后我们可以将此语句简化为:
Number.call(1, 0, [1, 4, 9, 16])
Number
函数将第一个参数转换为数字。忽略其他参数以及函数上下文。这意味着整个表达式可以简化为:
Number(0)
其中0
是index
。
这就是返回值为[0, 1, 2, 3]
的原因,因为它们是原始数组的索引。
不言而喻,原始代码示例不应该用于日常编程。整个系统可以更简单地使用:
[1, 4, 9, 16].map((value, index) => index)
即便如此,应该注意到原始值被无用地抛出。此类代码示例仅在探索特定语言行为的学术意义上有用,或者当您想要将您的朋友故意混淆为编码挑战的一部分时。
答案 1 :(得分:4)
输入参数为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
(当前索引)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.call
是Function.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;价值和提供的论据。