JavaScript 深入数组方法之 数组空位

72 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第16天,点击查看活动详情

数组是我们在 JavaScript 中最常用的数据形式,而数组中可以存储我们常说的简单类型和引用类型,那当遇到极少见的空位时我们在使用数组方法的时候应该注意什么呢?

什么是数组空位?

  • 数组空位,顾名思义,就是我们使用数组的时候,空下的位置,什么情况下会出现数组空位? 一种是我们自己声明的时候,另一种是我们修改了数组长度,或给数组指定位置赋值,但中间没有填充的时候,下面的截图是这两种情况的一个演示,在项目中这种情况极少,但并不代表不会出现。

Snipaste_2022-12-06_11-22-23.png

Snipaste_2022-12-06_11-33-42.png

跳过数组空位的情况

所谓跳过数组空位, 就是指我们在循环的时候,会直接跳过数组当中空位这一项,知道循环到不是空位只一项

  • 首先来看看都有哪些情况会跳过空位:
    forEach(),filter(),reduce(),every(),some(),for in 循环。 这几种情况,是完全跳过空位, 如下面这个截图一样:

Snipaste_2022-12-06_12-05-15.png 在循环当中我们无法遍历空位这一项的下标的值。

  • map() 会跳过空位,但是会保留这个值,也就是会保留这个空位:

Snipaste_2022-12-06_12-09-56.png
可以看到 map 方法循环当中是跳过空位的情况,但是我们得到的返回值还是会有空位,这就是源于 map 方法会保留原数组长度了。

  • join()toString()会将空位视为undefined,而undefinednull会被处理成空字符串。 Snipaste_2022-12-06_12-14-28.png

不跳过数组空位的情况(会将空位处理成undefined)

  • for循环,join(),toString(),Array.from(), ...扩展运算符,fill(),for of 循环,entries(),keys(),values(),find(),findIndex()

Snipaste_2022-12-06_12-16-55.png
我把最后的语句结果 undefined 码了,以免混淆大家的视听~ ,这些不跳过空位的方法,能够拿到空位的下标,空位的值就是 undefined~。

解析

那么我们遇到空位应该如何处理? 而这些方法底层又是如何处理的呢?我们可以分析他们底层的处理方式,从而发散一下思维,当我们触碰到这样的场景的时候便可以举一反三。

  • 我们在这里看一下 map 的实现(这次我使用defineProperties 这个api,我之前实现数组方法是直接挂载在原型上,使用 defineProperties 原理一样,但是更灵活,除了 value, 还可以设置其他三个属性,大家感兴趣可以自己调研一下哦):
Object.defineProperties(Array.prototype,{
  myMap:{
    value(cb,thisArg){
      let newArr = []
      for(let i = 0; i < this.length ; i++){
        if(!(i in this)) continue
        newArr[i] = cb.call(thisArg,this[i],i,this)
      }
      return newArr
    }
  }
})
let arr = [1,2,,3,4,,5]
let res = arr.myMap((item,index)=>{
  console.log(item,'----',index);
  return item
})
console.log(res);
// 大家可以思考一下,这里得到的结果都分别是什么呢?

揭晓答案 Snipaste_2022-12-06_12-27-47.png
这里我们实现了 跳过空位,但是我们得到的返回值,就和 map 一样, 长度是一样的,而且保留了空位。 那么在使用跳过空位的方法的时候,这些空位不需要我们来处理,因为已经跳过了, 使用没有跳过空位的方法的时候,我们就需要进行处理,就可以使用上面我们重构的 map 方法中的 i in this 这种对象访问方式来进行,来主动跳过空位了。