本文详细解析JavaScript中Array.prototype.map方法的实现原理。文章涵盖map的语法结构、回调函数参数及thisArg用法,重点探讨稀疏数组处理、长度缓存及索引访问机制。通过手动实现源码,展示如何模拟原生行为,包括类型检查与空槽跳过逻辑,帮助开发者深入理解数组迭代方法的底层细节。
Array.prototype.map()
map() 方法会创建一个新数组,其内容是由原数组中每个元素依次调用提供的回调函数后返回的结果组成的。需要注意的是,map() 本身不会修改原始数组,但如果在回调函数中修改了原数组元素,原数组仍会发生改变。
语法
map(callbackFn)
map(callbackFn, thisArg)
参数
map 方法接收两个参数:一个是回调函数,另一个是指定回调函数内部 this 指向的值。
1、callbackFn:针对数组中每个元素执行的函数。该函数的返回值会被作为新数组中对应的元素添加进去(是添加不是追加)。
调用该函数时,会传入以下参数:
- currentValue:当前正在处理的数组元素。
- index:当前元素在数组中的索引位置。
- array:调用 map() 方法的原始数组对象。
2、thisArg(可选):在执行 callbackFn 时,用作 this 上下文对象的值。
返回值
返回一个新数组,其每个元素均为回调函数的返回值。
用法
第一种(推荐)
const array = [1, 2, 3]
const newArray = array.map((currentValue, index, array) => {
// 返回新数组中的元素值
return currentValue + 1
})
// [2, 3, 4]
第二种(基于 this 进行操作时)
const thisArg = { name: 'Aimilali' }
const array = [1, 2, 3]
const newArray = array.map(function (currentValue, index, array) {
// 返回新数组中的元素值
return this.name + currentValue
}, thisArg)
// ['Aimilali1', 'Aimilali2', 'Aimilali3']
描述
map() 属于迭代方法。它遍历数组中的每个元素,调用一次提供的 callbackFn 函数,并利用返回结果构建并返回一个新数组。
callbackFn 仅会在那些已分配值的数组索引处被调用。它不会在稀疏数组中的空槽处被调用。
稀疏数组使用 map() 方法后返回值仍然是稀疏数组。空槽的索引在返回的数组中仍然为空,并且回调函数不会对它们进行调用。
请注意,在第一次调用 callbackFn之前,数组的长度已经被保存。因此:
- 当 map() 开始执行时,callbackFn 不会访问超出数组初始长度的任何新增元素。
- 对已经访问过的索引进行的修改,不会导致 callbackFn 在这些元素上再次被调用。
- 如果数组中某个尚未被访问的现有元素在 callbackFn 执行期间被修改,那么传递给 callbackFn 的值将是该元素修改后的最新值。
被删除的元素则不会被访问。
这类并发修改往往会导致代码逻辑难以理解,通常应当避免(除非有特殊情况)。
map() 方法是通用的。它仅要求 this 值具备 length 属性和整数键属性。
由于 map 创建一个新数组,在不使用 map 返回的新数组的情况下不推荐使用 map。应该使用 forEach 或 for...of 作为代替。
实现 map 方法
根据上述 map 的描述,在手动实现 map 时需重点注意以下三点。
- 在调用回调函数之前,需先保存数组的长度。
- 回调函数不会在稀疏数组的空槽位置被调用。
- 稀疏数组经过 map() 处理后,返回值依然保持为稀疏数组。
Array.prototype.myMap = function (fun, context) {
if (!Object.is(typeof fun, 'function')) {
throw TypeError(`${typeof fun} is not a function`)
}
const length = this.length // 保存数组长度
const newArr = Array(length)
for (let i = 0; i < length; i++) {
if (Object.hasOwn(this, i)) { // 跳过稀疏数组
newArr[i] = fun.call(context, this[i], i, this) // 确保返回值仍然是稀疏数组
}
}
return newArr
}
结语
至此,Array 实例方法 map 的手动实现过程已完成。
JavaScript 中的 Array 类型提供了一系列强大的实例方法。在 Array 实例方法实现系列专栏中,我将深入探讨一些常见的 Array 实例方法,解析它们的实现原理。
如果有错误或者不严谨的地方,请大家务必给予指正,十分感谢。欢迎大家在评论区中讨论。
以上就是JavaScript中Array实例方法map的实现方法的详细内容,更多关于JavaScript Array map实现的资料请关注本站其它相关文章!