上面代码中,数组的成员是三个undefined
,数组a2
的成员是三个空位。这两个数组很相似,长度都是 3,每个位置的成员读取出来都是undefined
。
但是,它们实际上存在重大差异。
0 in a1 // true
0 in a2 // false
a2.hasOwnProperty(0) // false
Object.keys(a1) // ["0", "1", "2"]
a1.map(n => 1) // [1, 1, 1]
a2.map(n => 1) // [, , ,]
上面代码一共列出了四种运算,数组a1
和a2
的结果都不一样。前三种运算(in
运算符、数组的hasOwnProperty
方法、Object.keys
方法)都说明,数组a2
取不到属性名。最后一种运算(数组的map
方法)说明,数组没有发生遍历。
规格的给出了答案。
翻译如下。
上面的规格说得很清楚,数组的空位会反映在length
属性,也就是说空位有自己的位置,但是这个位置的值是未定义,即这个值是不存在的。如果一定要读取,结果就是undefined
(因为undefined
在 JavaScript 语言中表示不存在)。
这就解释了为什么in
运算符、数组的hasOwnProperty
方法、方法,都取不到空位的属性名。因为这个属性名根本就不存在,规格里面没说要为空位分配属性名(位置索引),只说要为下一个元素的位置索引加 1。
至于为什么数组的map
方法会跳过空位,请看下一节。