'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
。
这里有两个 this
引用的绑定:
this
用于 map
函数的执行上下文
this
为回调函数的执行上下文
它们彼此不相关。
map
的第二个参数指定 this
将用于回调。如果不提供,则默认为undefined
(不是数组)。
map.call
的第一个参数决定了 this
对 map
的作用——以及迭代哪个数组的结果。
这在mdn上提供的polyfill中也有体现:完全符合这些规范:O
为map
获取this
的值函数,并且 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)
中,effector
中的this
将是letters
。由于 effector
(在第一个版本中)不关心 this
是什么,该参数基本上没有效果,numbers
的内容被记录下来。
另一方面,在numbers.map.call(letters, effector)
中,numbers.map
的this
设置为letters
。这实际上意味着 map
方法虽然在 numbers
上调用,但被“劫持”到记录 letters
的条目。
第二个示例的工作原理类似 - 关键是 函数 this
设置在:effector
在一种情况下,numbers.map
在另一个.
我一直在刷新 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
。
这里有两个 this
引用的绑定:
this
用于map
函数的执行上下文this
为回调函数的执行上下文
它们彼此不相关。
map
的第二个参数指定 this
将用于回调。如果不提供,则默认为undefined
(不是数组)。
map.call
的第一个参数决定了 this
对 map
的作用——以及迭代哪个数组的结果。
这在mdn上提供的polyfill中也有体现:完全符合这些规范:O
为map
获取this
的值函数,并且 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)
中,effector
中的this
将是letters
。由于 effector
(在第一个版本中)不关心 this
是什么,该参数基本上没有效果,numbers
的内容被记录下来。
另一方面,在numbers.map.call(letters, effector)
中,numbers.map
的this
设置为letters
。这实际上意味着 map
方法虽然在 numbers
上调用,但被“劫持”到记录 letters
的条目。
第二个示例的工作原理类似 - 关键是 函数 this
设置在:effector
在一种情况下,numbers.map
在另一个.