3

问题复现

var arr = ['a', 'b', 'c'];
var sid = ['Go'];
for (var key in arr) {
    sid[key + 1] = arr[key];
}
console.log(sid)

很简单的问题,最后的输出结果却是:

[ 'Go', , , , , , , , , , , 'b', , , , , , , , , , 'c' ]

问题分析

通过上面的输入结果我们可以发现这么几个问题:

  1. sid里面多了很多空项,length明显的增多了

  2. arr[0]的值在sid中没有出现

问题1:sid里面多了很多空项,length明显的增多了

略过痛苦的分析步骤直接来重点内容:
通过打印key + 1我们可以找到问题的关键。通过打印我们可以得到如下信息。
在第一次循环的时候key + 1的值为01,此后依次为:11,21
通过这个我们可以判断: 这个key其实是一个String类型的
所以上面的步骤相当于:

sid['01'] = arr[0];
sid['11'] = arr[1];
sid['21'] = arr[2];

究其原因,我只能在浅层面作出解释:
这可能是因为for-in一般是用于对象的(狭义的对象),而对象的属性是一个String类型,所以for-in的参数key被定义为一个String类型。这并没有考虑过数组的属性名(下标)不是String类型,而是一个Number类型的情况。所以就出现了上面的问题。此外在MDN的js语法关于for-in这块出现过这样的提示:

Note: for..in 不应该被用来迭代一个下标顺序很重要的 Array .

可能就包含这种情况吧。

问题2:arr[0]的值在sid中没有出现

arr[0]的值其实通过sid['01']可以取到。
此外,在node下打印sid的时候可能与在console中打印出现不同的结果。

问题解决

对于数组的遍历,最好使用:forEach,map,some,filter,find等方法。尤其是是这种牵扯到数组下标的尽量不要使用for-in来处理,如果非要使用可以做如下处理:

var arr = ['a', 'b', 'c'];
var sid = ['Go'];
for (var key in arr) {
    sid[parseInt(key) + 1] = arr[key];
}
console.log(sid)

以避免如上的问题。


aqiongbei
2k 声望281 粉丝

人生路上,你走的每一步都算数