for...in本身是Object的遍历方法,js中的数组也继承自Object,所以也能够使用for...in遍历出属性。然而for...in遍历数组时有一些细节需要注意。
1、for...in遍历的属性是字符串,而不是数字
const arr = [1, 2, 3] for (const i in arr) { console.log(i, typeof i) }
打印结果:
2、for...in遍历的是对象的可枚举属性,包括原型链上的属性
const obj = { a: 'a', b: 'b' } Object.prototype.c = 'c' Object.defineProperty(obj, 'd', { value: 'd', enumerable: true // enumerable默认值为false,设置为true时可以被for...in遍历到 }) for (const i in obj) { console.log(i, obj[i]) }
打印结果:defineProperty中enumerable的默认值是false,for...in遍历不到,如果设置为true即可被for...in遍历到
3、遍历的顺序是对象属性的枚举顺序,不是按照数组的下标顺序遍历
如果需要按照索引顺序去遍历,不要使用for...in去遍历,而应该使用for...of或者for循环、forEach等方法。
此外,因为有稀疏数组的存在,其实JS里的数组不一定是顺序结构存储的。当数组的键分布较为稀疏,为了充分节约空间,数组可能会退化为像对象一样的哈希表存储结构。