你所了解的数组空位

# 什么是数组空位

形象地说,公交车上,无人坐的位置,就是空位(子)

相反,只要被占用就不是空位,无论是坐人了,还是放了私人物品

而数组的空位与之类似

当数组下标索引位无任何值时索引位就是空位

值得注意的是,虽然索引位无任何值

但通过下标访问时值为 undefined

就像访问对象上不存在的属性一样

创建空位数组有几种方式:

// 字面量
let arr = [, , ,]

// 构造函数
let arr = new Array(3)

// length
let arr = []
arr.length = 3
1
2
3
4
5
6
7
8
9

值得注意的是数组空位访问虽然值是 undefined

但与直接使用 undefined 初始化数组完全是两回事

// 使用 undefined 初始化数组
let arr = [undefined, undefined, undefined]
1
2

很显然,数组的索引位有值了,虽然值为令人迷惑的 undefined

此时就不是空位数组了

数组的空位在浏览器控制台与 Nodejs 表现类似

// 浏览器控制台
 Array(3) // (3) [empty × 3]

// Nodejs
Array(3) // [ <3 empty items> ]
1
2
3
4
5

# 数组空位检测

空位虽然上面没有任何值,但依然占据长度 length

比如下面数组长度是 4,不是 3

let arr = [1, , 2, 3] // length 4
1

如何检测数组中空位?

使用 in 操作符或 hasOwnProperty 方法

1 in arr // false,数组索引 1 是空位 - 不推荐

// hasOwnProperty 与 in 类似
arr.hasOwnProperty(1) // false
1
2
3
4

上述方法不够灵活,因为空位索引是任意的

map + includes 方法

arr.map(v => arr.includes(v)).includes() // true, 数组包含空位,注意 includes 不传任何参数 - 推荐
1

原理:map 对于数组空位,跳过不处理,但在结果中保留

includes 方法把空位当成 undefined 处理

includes 不传参数时,参数默认为 undefined

includes() 与 includes(undefined) 等价

一些教程上说,includes 第一个参数必须,测试得知,此说法是错的

另外

试图通过数组索引或 at 方法获取空位值是获取不到的,空位上本就无值 所以结果默认都是 undefined

# 不了解数组空位产生的 bug

在此之前我是不知道的,需求是原动力

先看下祖传的源代码

创建 7 项二维数组

let dataArr = Array(7).map(() => [])
1

我以为结果是 [[], [], [], [], [], [], []]

但实际结果 [empty × 7]

一脸懵逼 ...

但看到 empty 勾起曾经看过关于数组空位的文档使用说明

这该死的记忆

map 遍历成员,空位不处理,直接跳过,而且不会进行回调处理,但在结果中会保留

意思就是上面的 map 方法的回调根本就没有执行

因为成员全是空位

所以返回一个全是空位的新数组

测试下:

let dataArr = Array(7).map(() => console.log(1))
1

正常 map 回调执行应该打印 7 次 1

结果是没有一次打印

数组对于空位处理方式除了上述的方式外

还有当成 undefined 处理

或者跳过并在结果中忽略

# 数组空位处理大全

数组方法对于空位处理有 3 种方式:

跳过,不处理:表示如果磁到索引位是空位时,不会进入回调函数,直接跳过

1. 跳过,不处理,结果中原样保留空位

  • map
  • toString
  • toLocaleString
  • concat
  • copyWithin
  • push
  • pop
  • reversse
  • unshift
  • shift
  • slice
  • splice
  • sort

列举两个比较特殊的:

let arr = [10, , 3]

// [10, , 3]
arr.map(v => {
  console.log(v) // 只打印 10, 3,空位由于跳示,不处理,所以不打印
  return v
}) [

// [10, 3, ,],空位始终位于最后
arr.sort()
1
2
3
4
5
6
7
8
9
10

2. 跳过,不处理,结果中不保留空位(当数组不存在空位处理)

  • indexOf
  • lastIndexOf
  • forEach
  • filter
  • flat
  • flatMap
  • every
  • some
  • reduce
  • reduceRight
// [10, 3]
arr.flat()

// true
arr.every(v => v)

// false
arr.some(v => !v)

// 13
arr.reduce((acc, cur) => acc + cur)
1
2
3
4
5
6
7
8
9
10
11

3. 转成 undefined 或当正常元素处理

  • find
  • findIndex
  • includes
  • join
  • entries
  • values
  • Array.from
  • [...arr]
  • fill: 当正常元素处理
// [2, 2, 2]
arr.fill(2)

// [10, undefined, 3]
Array.from(arr)

// [10, undefined, 3]
console.log([...arr])
1
2
3
4
5
6
7
8

上图比逼逼更直接:

数组空位总结

# 小结

知晓什么是数组空位

产生的方式及检测方法

以及在数组方法中的具体表现

避免踩坑

于实际开发中数组空位出现概率比较小

没有谁想着要创建空位数组

于特定需求中注意即可

# 一些想法

数组空位的产生,增加了心智负担

需要比细节更细 ...

但想想,为什么会出现数组空位这个东西

产生它的需求是什么?

大胆猜想下,可能是因为 Array(n) 的怪异行为

把传入的数字 n 理解为要创建长度为多少的数组

于是,多出来的索引位,用什么填充合适呢?

使用 undefined、null 等基本类型值?

或者发明新的占位符之类的?(这又要增加学习负担了)

无论哪种都不太合适

于是保持原状,既然没有任何值,没有就好了,何必自寻烦恼

另外一种猜想

产品需求导致的语法不得不如此设计,哈哈哈哈...

# 参考

扫一扫,微信中打开

微信二维码