问题描述
我一直在刷新关于call()
上map()
和NodeList
用法的JavaScript知识。
通过Google进行搜索非常容易,call()
应该做些什么,并且有一些资源说明了如何与map()
一起使用。
但是,正如我在MDN上注意到的那样,map()
函数也可以使用第二个参数,该参数应该为this
设置map()
关键字-至少我就是这样认为应该这样做。
我试图用简单的数组自己检查一下:
var numbers = [1,2,3];
var letters = ['a','b','c'];
..并且具有一个简单的功能,即将作为map()
的参数:
var effector = function (x) {
console.log(x);
}
现在,我不明白的是为什么这两个函数调用具有不同的结果:
numbers.map(effector,letters);
numbers.map.call(letters,effector);
我希望它们都向控制台输出字母,因为两个this
关键字都应引用它们(分别引用它们的对象)。
我做了一些进一步的研究,并尝试使用这种修饰的效应子功能:
var effector = function () {
console.log(this);
}
..再次:
numbers.map(effector,effector);
假设我们处于“严格使用”状态,则第一个通话记录为letters
,第二个通话记录为undefined
。
但是同样,我希望这两个调用都能产生相同的输出。
我想念什么?
编辑:
我正在阅读.map
可以如何进行填充,如果在MDN上进行检查,就会看到callback.call()
中如何使用.map的第二个参数。
我想,最后,即使callback.call()
也应与this
中的.map
相同。
解决方法
这里this
引用有两个绑定:
-
this
用于map
函数的执行上下文 -
this
用于回调函数的执行上下文
它们彼此不相关。
map
的第二个参数指示用于回调的this
。如果未提供,则默认值为undefined
(而不是数组)。
map.call
的第一个参数指示this
对map
的含义-并因此迭代哪个数组。
这也反映在mdn上提供的polyfill中:完全符合以下规范:O
获得this
函数的map
值, T
获得回调的this
值。它们通常是不同的。
map
与forEach
与您的问题无关,但值得一提:当您实际上没有映射任何内容时,请不要使用map
。 map
用于创建一个新数组,该数组中的每个值都通过在同一索引的原始值上调用回调函数来映射到每个值。
但是,当您只需要迭代数组值而无意执行此类映射时,请使用forEach
方法或for...of
循环。两者都可以直接在NodeList
上使用,而无需.call
。
numbers.map(effector,letters)
和numbers.map.call(letters,effector)
之间的区别在于哪个功能 this
设置为letters
。
在第一个中,如MDN所述,第二个参数是在回调中用作this
的值-即提供给map
的参数。也就是说,在numbers.map(effector,letters)
中,this
内的effector
将是letters
。由于effector
(在第一个版本中)并不关心this
是什么,因此该参数基本上无效,并且记录了numbers
的内容。
另一方面,在numbers.map.call(letters,effector)
中,numbers.map
的{{1}}设置为this
。实际上,这意味着letters
方法尽管被map
调用,但是却被“劫持”以记录numbers
的条目。
第二个示例的工作原理类似-关键是哪个{em>函数设置了letters
:在一种情况下设置this
,在另一种情况下设置effector
。