Неясный способ проверки на собственные свойства
В книге Javascript: полное руководство Шестого издания Дэвида Фланагана, стр. 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;
Так почему же автор использует такое сложное выражение?
Я что-то здесь упускаю?
1 ответ
Нет, вот несколько примеров, которые потерпят неудачу:
Число с плавающей точкой:
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.abs
а также Math.floor
звонки охраняют от.
Кстати, действительно нет никакого преимущества в использовании цикла for для индексов массива. Я бы порекомендовал использовать цикл на основе индекса.