Array 实例方法 map 的实现

Array.prototype.map()

map() 方法创建一个新数组,其结果是原数组中的每个元素都调用一个提供的函数后返回的结果。 map() 方法不会改变原数组,然而接受的回调函数可以改变原数组。

语法

js 复制代码
map(callbackFn) 
map(callbackFn, thisArg)

参数

map 方法接受两个参数:回调函数 和 指定回调函数中的 this 值。

1、callbackFn:为数组中的每个元素执行的函数。它的返回值作为一个元素被添加到新数组中(是添加不是追加)

该函数被调用时将传入以下参数:

  • currentValue:数组中当前正在处理的元素。
  • index:正在处理的元素在数组中的索引。
  • array:调用了 map() 的数组本身。

2、thisArg(可选):执行 callbackFn 时用作 this 的值。

返回值

一个新数组,每个元素都是回调函数的返回值。

用法

第一种(推荐)

js 复制代码
const array = [1, 2, 3]
const newArray = array.map((currentValue, index, array) => {
    // 返回新数组中的元素值
    return currentValue + 1
})
// [2, 3, 4]

第二种(基于 this 进行操作时)

js 复制代码
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() 方法后返回值仍然是稀疏数组。
js 复制代码
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 实例方法,解析它们的实现原理。

如果有错误或者不严谨的地方,请大家务必给予指正,十分感谢。欢迎大家在评论区中讨论。

相关推荐
刘发财3 小时前
弃用html2pdf.js,这个html转pdf方案能力是它的几十倍
前端·javascript·github
ssshooter10 小时前
看完就懂 useSyncExternalStore
前端·javascript·react.js
Live0000011 小时前
在鸿蒙中使用 Repeat 渲染嵌套列表,修改内层列表的一个元素,页面不会更新
前端·javascript·react native
柳杉11 小时前
使用Ai从零开发智慧水利态势感知大屏(开源)
前端·javascript·数据可视化
球球pick小樱花11 小时前
游戏官网前端工具库:海内外案例解析
前端·javascript·css
喝水的长颈鹿12 小时前
【大白话前端 02】网页从解析到绘制的全流程
前端·javascript
用户145369814587812 小时前
VersionCheck.js - 让前端版本更新变得简单优雅
前端·javascript
codingWhat12 小时前
整理「祖传」代码,就是在开发脚手架?
前端·javascript·node.js
码路飞12 小时前
写了个 AI 聊天页面,被 5 种流式格式折腾了一整天 😭
javascript·python
Lee川12 小时前
优雅进化的JavaScript:从ES6+新特性看现代前端开发范式
javascript·面试