4

在本书 Javascript:David Flanagan 的权威指南第六版第 147 页中,作者讨论了使用 for..in 循环遍历数组时的警告,以下是引用(粗体是我的)

...因此,您不应在数组上使用 for/in 循环,除非您包含额外的测试来过滤掉不需要的属性。 您可以使用以下任一测试

for(var i in a) {
   if (!a.hasOwnProperty(i)) continue; // Skip inherited properties
   // loop body here
}

for(var i in a) {
   // Skip i if it is not a non-negative integer
   if (String(Math.floor(Math.abs(Number(i)))) !== i) continue;
}

现在第一个代码片段对我来说很清楚,继承的属性将被跳过。

但是,我根本不清楚第二个代码片段。

据我了解,第二个代码片段将跳过数组的任何非数字属性(无论它是否是自己的属性(与第一个代码片段不同))

但如果是这样的话,你不能只使用一个简化的测试,比如:

if (Number(i) != i) continue;

那么作者为什么要用这么复杂的表达方式呢?

我在这里错过了什么吗?

4

1 回答 1

2

不,这里有一些会失败的例子:

浮点数:

var a = [1, 2, 3];
a['1.5'] = 'busted';
for(var i in a) {
    if (Number(i) != i) continue;
    document.getElementById('output1').textContent += i + '\n';
}
for(var i in a) {
    if (String(Math.floor(Math.abs(Number(i)))) !== i) continue;
    document.getElementById('output2').textContent += i + '\n';
}
<h3>Number(i) != i</h3>
<pre id="output1"></pre>
<h3>String(Math.floor(Math.abs(Number(i)))) !== i</h3>
<pre id="output2"></pre>

负数:

var a = [1, 2, 3];
a['-5'] = 'busted';
for(var i in a) {
    if (Number(i) != i) continue;
    document.getElementById('output1').textContent += i + '\n';
}
for(var i in a) {
    if (String(Math.floor(Math.abs(Number(i)))) !== i) continue;
    document.getElementById('output2').textContent += i + '\n';
}
<h3>Number(i) != i</h3>
<pre id="output1"></pre>
<h3>String(Math.floor(Math.abs(Number(i)))) !== i</h3>
<pre id="output2"></pre>

这是Math.absandMath.floor调用所要防范的。

顺便说一句,对数组索引使用 for in 循环确实没有任何优势。我建议使用基于索引的循环。

于 2015-11-29T08:09:39.887 回答