new Array(4) 有 4 个元素吗?
从一个生成验证码的方法说起
这段代码是在最近的一个需求中生成验证码的方法。暂定的需求是 4 位数字,为了拓展性位数和范围都设置成了参数。
const createRandomCode = (len = 4, radix = 10) => {
const randomString = Math.random().toString(radix).slice(2)
const codeList = new Array(4)
return codeList.map(() => {
const randomIndex = Math.floor(Math.random() * randomString.length)
return randomString[randomIndex]
}).join('')
}
初看代码没有发现问题,运行一下就会发现返回值为 '' 。
出问题的 new Array()
从返回值可以倒推出问题在 const codeList = new Array(4) 上。我们希·望通过 new Array(len) 方法生成一个长度为 len 的数组。但实际生成的仅仅只包含一个 length 属性而已,实际数组中并没有任何值。因此在使用 map 的时候没有元素可以遍历。
在 Chrome 的控制台中可以看到 codeList 显示为 empty。
在 MDN 中对于 new Array() 的参数有一段说明。使用 new Array() 创建的数组和传入的参数数量有关。当只传入一个参数时,只会返回一个只有 length 属性的对象。
❝「elementN」 Array 构造器会根据给定的元素创建一个 JavaScript 数组,但是当仅有一个参数且为数字时除外(详见下面的 arrayLength 参数)。注意,后面这种情况仅适用于用 Array 构造器创建数组,而不适用于用方括号创建的数组字面量。
❞
❝「arrayLength」 一个范围在 0 到 232-1 之间的整数,此时将返回一个 length 的值等于 arrayLength 的数组对象(「言外之意就是该数组此时并没有包含任何实际的元素,不能理所当然地认为它包含 arrayLength 个值为 undefined 的元素」)。如果传入的参数不是有效值,则会抛出 RangeError 异常。
❞
顺带说一句,即使直接使用 [] 也能创建出只带 length 的数组对象。
解决方法
既然问题出在没有元素上,那么我们只要填充上元素即可。( for 循环不是很优雅,就忽略了)
Array.fill 方法可以为数组填充上初始元素。由于这里对初始值没有要求,只需要修改 new Array(4).fill(undefined) 即可。
或者可以使用 ES6 数组展开。与 Array.fill 的区别在于,数组展开后每个元素都是 undefined。
本文首发于公众号:「“此方的手账”」 一个分享技术和生活感悟的公众号,欢迎大家来玩。
本文使用 mdnice 排版