解析FEN棋谱时JavaScript中String.split()结合for...in循环表现不符合预期的问题
为什么for...in循环遍历数组输出的是索引而非元素?
这是一个很典型的JavaScript数组遍历误区——问题出在for...in循环的核心工作逻辑上!
问题根源:for...in遍历的是对象的属性键
在JavaScript里,数组本质上是一种特殊的对象,数组的索引其实就是对象的属性键(字符串类型,比如"0"、"1")。当你使用for...in循环遍历数组时,它并不会直接遍历数组的元素,而是遍历数组对象的所有可枚举属性键,也就是那些索引值。
回到你的代码:
const locations = defaultFEN.split(" ")[0]; for (let rank in locations.split("/")) { console.log(rank); }
这里locations.split("/")得到的是包含8个元素的数组:["rnbqkbnr", "pppppppp", "8", "8", "8", "8", "PPPPPPPP", "RNBQKBNR"]。for...in循环遍历这个数组的属性键,也就是"0"到"7",控制台输出时会自动把这些字符串转换成数字显示,所以你看到的是0-7,而不是期望的数组元素。
而当你用console.log(locations.split("/")[i])时,你是通过索引主动获取对应位置的元素,所以能得到正确结果。
正确的数组遍历方式
如果想遍历数组的元素,推荐以下几种方法:
- 普通基于索引的for循环(兼容所有环境):
const ranks = locations.split("/"); for (let i = 0; i < ranks.length; i++) { console.log(ranks[i]); }
- for...of循环(ES6+,简洁直接遍历元素):
for (const rank of locations.split("/")) { console.log(rank); }
- 数组forEach方法(函数式风格,适合简单遍历):
locations.split("/").forEach(rank => { console.log(rank); });
额外提醒:为什么for...in不适合数组?
除了返回索引的问题,for...in还会遍历数组原型链上的所有可枚举属性。比如如果有人给Array.prototype添加了自定义属性,这些属性也会被for...in遍历到,导致意外结果。所以遍历数组时,优先使用上面提到的三种方法。
内容的提问来源于stack exchange,提问作者Justin DeWitt
相关产品推荐
相关产品推荐

