为什么访问给定位置旁边的元素会出现错误,而访问前一个元素却能正常工作?

Why does accessing the element next to the given position misbehave, whereas accessing the previous element works correctly?

给定以下一段简单的 Javascript 代码:

var a = [ 1, 2, 3 ]

for ( var i in a ) {
    console.log(a[i-1], a[i], a[i+1]);
}

为什么会产生下面奇怪的输出?

undefined 1 undefined
1 2 undefined
2 3 undefined

第一行的第一个undefined和最后一行的最后一个undefined是因为越界访问。但是另外两个 undefined 是从哪里来的呢?

稍作修改的测试用例很好地暴露了问题:

$ cat test.js 
var a = [ 1, 2, 3 ]

for ( var i in a ) {
    console.log(i-1, i, i+1);
    console.log(a[i-1], a[i], a[i+1]);
    console.log('--------');
}

$ nodejs test.js 
-1 '0' '01'
undefined 1 undefined
--------
0 '1' '11'
1 2 undefined
--------
1 '2' '21'
2 3 undefined
--------

所以,变量i字符串类型。当使用它来访问前一个元素时,Javascript 是一种弱类型语言,解释器发现表达式 i-1 只有在 i 转换为数字时才有意义。为了公平起见(和程序员的生活有趣),在表达式 i+1 中,解释器将 1 转换为字符串并将 + 视为连接,生成数组中缺少的键(或者,如果数组足够长,将访问错误的元素:a[11] 而不是 a[2]a[21] 而不是 a[3],等等)。

在这种特殊情况下,问题来自数组循环的不正确方式(如果这个问题的答案对您来说不是很明显,请仔细阅读 excellent explanation of how to iterate over arrays in JavaScript)。但是,在本应为数字的变量实际上包含字符串值的任何其他情况下(例如,在解析文本数据时忘记进行转换),它可能会咬你。