Каков наилучший способ перебора элементов в javascript?
Недавно я пришел к другому способу петли, хотя массив в Javascript.
Я использовал для записи петли что-то вроде этого:
for (var len = 0; len < testData.length; len++) {
total = total + testData[len];
}
Я прочитал код, который сделал это следующим образом:
for (var len = 0; testData[len]; len++) {
total = total + testData[len];
}
Мне было интересно, как они будут работать, поэтому я нашел jsPerf, чтобы узнать это. Результаты довольно изумительны. Я ожидал, что второй метод будет немного быстрее, чем первый, но на самом деле намного, намного быстрее.
Есть ли здесь нисходящая сторона? Или это лучший способ перебрать элементы списка.
Update:
Состояние серого приближается, и Diode указал мне на простой недостаток в тестовом файле, который, по-видимому, был быстрее.
После исправления ошибки это самый быстрый:
var datalen = testData.length;
for (var len = 0; len <datalen; len++) {
total = total + testData[len];
}
Обновление 2:
После тестирования в некоторых других браузерах этот тестовый тест снова принимает другое направление.
Только в Chrome и Opera обычный для цикла самый быстрый. В других других браузерах путь Шмиддти только немного быстрее.
var i = testData.length, sum=0;
while (i--){
sum += testData[i];
}
Ответы
Ответ 1
Вы также можете сделать такой цикл:
var i = testData.length;
while (i--){
console.log(testData[i]);
}
Обратите внимание, что он перемещает массив назад.
Или, для суммирования:
var i = testData.length, sum=0;
while (i--){
sum += testData[i];
}
Ответ 2
Я бы сказал, что первая форма лучше. Вторая форма имеет некоторые проблемы. Что делать, если у вас есть разреженный массив, содержащий значения falsy
? Например: var testData = [ "text", undefined, false, 0, 5 ];
Я также ожидаю, что первая форма будет работать лучше. Особенно, если вы "кешируете" значение testData.length
Так же:
var i, len = testData.length;
for (i = 0; i < len; i += 1) {
total = total + testData[i];
}
Ответ 3
ОБНОВЛЕНИЕ: я был неправ, forEach
очень медленный! Кажется, петли лучше
Вы должны использовать forEach
, который определен в 5-м выпуске ECMAScript.
testData.forEach(function(val,i,arr){
total += val;
});
Аргументы:
-
val
- текущее значение
-
i
- текущий индекс
-
arr
- это массив
вам не нужно использовать все из них:
testData.forEach(function(val){
total += val;
});
И для браузеров, которые его не поддерживают, эту прокладку можно использовать:
if(!Array.prototype.forEach){
Array.prototype.forEach = function(fn, scope) {
for(var i = 0, len = this.length; i < len; ++i) {
fn.call(scope || this, this[i], i, this);
}
}
}
Подробнее см. Array.forEach.
Ответ 4
Основываясь на ответе Shmiddt, вы можете использовать цикл назад. кажется, что это немного быстрее, чем когда-либо назад в Firefox, а в Chrome они связаны:
var total = 0;
for (var len = testData.length-1; len >=0; len--) {
total += testData[len];
}
Тест: http://jsperf.com/for-until-length-vs-until-undefined/10
Ответ 5
Что касается производительности, testData[len]
просто проверяет, определен ли элемент, а не null/false/ "falsish", что быстрее, чем сравнение, и особенно получение testData.length для каждой итерации.
Итак, второй способ быстрее, но не более надежный - как правильно заявил Фритц ван Кампен.
Ответ 6
Ваш код установки вставляет 0, что заставляет цикл прерывать первое условие
var testData = [];
for (var i = 0; i < 1000; i++) {
testData.push(i); // pushes 0 to `testData`
}
for (var len = 0; testData[len]; len++) { // loop breaks on first condition-check as testData[0] is 0.
total = total + testData[len];
}
Измените установочный код, как показано ниже, и посмотрите разницу
var testData = [];
for (var i = 0; i < 1000; i++) {
testData.push(i+1);
}
http://jsperf.com/for-until-length-vs-until-undefined/6