'this' 关键字在 map() 和 call() 中如何工作?

How does 'this' keyword work in map() and call()?

我一直在刷新 JavaScript 关于 call()map()NodeList 上的用法的知识。

google 相当容易,call() 应该做什么,并且有一些资源包含它如何与 map() 一起使用的示例。

然而,正如我在 MDN 上注意到的那样,map() 函数也可以接受第二个参数,它应该为 map() 设置 this 关键字——或者至少是我认为它应该做什么。

我尝试用简单的数组自己检查:

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, letters);
numbers.map.call(letters, effector);

假设我们处于“严格使用”状态,第一个调用记录 letters,第二个记录 undefined

但是,我希望这两个调用产生相同的输出。

我错过了什么?

编辑:

我在读,.map 是如何被填充的,如果你在 MDN 上查看它,你会看到,.map 的第二个参数是如何在 callback.call().[=34= 中使用的]

我想,最终,即使 callback.call() 也应该具有与 .map 相同的 this

MDN - map

这里有两个 this 引用的绑定:

  • this 用于 map 函数的执行上下文
  • this为回调函数的执行上下文

它们彼此不相关。

map 的第二个参数指定 this 将用于回调。如果不提供,则默认为undefined(不是数组)。

map.call 的第一个参数决定了 thismap 的作用——以及迭代哪个数组的结果。

这在mdn上提供的polyfill中也有体现:完全符合这些规范:Omap获取this的值函数,并且 T 获取回调的 this 的值。它们通常是不同的。

map 对比 forEach

与你的问题无关,但值得一提:当你实际上没有映射任何东西时,不要使用mapmap 旨在创建一个新数组,其中每个值都已通过调用同一索引处原始值的回调函数进行映射。

然而,如果您只需要迭代数组值,而不打算执行此类映射,则使用 forEach 方法或 for...of 循环。这两个都可以在 NodeList 上开箱即用,不需要 .call.

numbers.map(effector, letters)numbers.map.call(letters, effector)的区别在于哪个函数this设置为letters

在第一个中,正如 MDN 所解释的那样,第二个参数是在回调中用作 this 的值 - 即提供给 map 的参数。也就是说,在numbers.map(effector, letters)中,effector中的this将是letters。由于 effector(在第一个版本中)不关心 this 是什么,该参数基本上没有效果,numbers 的内容被记录下来。

另一方面,在numbers.map.call(letters, effector)中,numbers.mapthis设置为letters。这实际上意味着 map 方法虽然在 numbers 上调用,但被“劫持”到记录 letters 的条目。

第二个示例的工作原理类似 - 关键是 函数 this 设置在:effector 在一种情况下,numbers.map 在另一个.