上面代码中,数组的成员是三个undefined,数组a2的成员是三个空位。这两个数组很相似,长度都是 3,每个位置的成员读取出来都是undefined

    但是,它们实际上存在重大差异。

    1. 0 in a1 // true
    2. 0 in a2 // false
    3. a2.hasOwnProperty(0) // false
    4. Object.keys(a1) // ["0", "1", "2"]
    5. a1.map(n => 1) // [1, 1, 1]
    6. a2.map(n => 1) // [, , ,]

    上面代码一共列出了四种运算,数组a1a2的结果都不一样。前三种运算(in运算符、数组的hasOwnProperty方法、Object.keys方法)都说明,数组a2取不到属性名。最后一种运算(数组的map方法)说明,数组没有发生遍历。

    规格的给出了答案。

    翻译如下。

    上面的规格说得很清楚,数组的空位会反映在length属性,也就是说空位有自己的位置,但是这个位置的值是未定义,即这个值是不存在的。如果一定要读取,结果就是undefined(因为undefined在 JavaScript 语言中表示不存在)。

    这就解释了为什么in运算符、数组的hasOwnProperty方法、方法,都取不到空位的属性名。因为这个属性名根本就不存在,规格里面没说要为空位分配属性名(位置索引),只说要为下一个元素的位置索引加 1。

    至于为什么数组的map方法会跳过空位,请看下一节。