You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现Array.prototype.map的两种方式差异及无限循环问题咨询

自定义Array.map实现的差异与无限循环问题解析

先看两个实现的核心代码:

版本1(使用i < this.length)

Array.prototype.myMap = function (cb, thisArg) {
    const newArr = []
    for (let i = 0; i < this.length; i++) {
        if (i in this) {
            newArr[i] = cb.call(thisArg, this[i], i, this)
        }
    }
    return newArr
}

版本2(缓存len = this.length)

Array.prototype.myMap = function (cb, thisArg) {
    const newArr = []
    const len = this.length
    for (let i = 0; i < len; i++) {
        if (i in this) {
            newArr[i] = cb.call(thisArg, this[i], i, this)
        }
    }
    return newArr
}

两者的核心差异

两个实现的唯一区别在于循环终止条件的取值时机:

  • 版本1每次循环都会重新读取原数组(this)的length属性,用实时的数组长度判断是否继续循环。
  • 版本2在循环开始前就把原数组的初始长度缓存到len变量里,后续循环只对比这个固定值,不再读取实时的this.length。

无限循环的原因

当传入的回调函数cb在执行过程中修改了原数组的长度(比如给原数组新增元素),版本1就会触发无限循环:
比如原数组初始长度是2,当i循环到1时,回调里给原数组push了一个新元素,此时this.length变成3。下一次循环i变成2,判断2 < 3成立,继续执行回调;如果回调里又给原数组新增元素,this.length会继续变大,i永远追不上实时增长的length,循环就永远停不下来。

而版本2因为提前缓存了初始的数组长度,不管回调怎么修改原数组的实时长度,循环都会在i等于初始len时终止,不会出现无限循环的问题。

另外补充:代码里的if (i in this)是用来处理稀疏数组的,避免对不存在的数组索引执行回调,这个逻辑和无限循环问题无关。

内容的提问来源于stack exchange,提问作者tomsma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 03:45:40