Каков наилучший способ перебирать элементы в 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:

серое состояние наступает , и Диод указали мне на простой недостаток в тесте, который сделан, кажется, быстрее.

После исправления ошибки это самый быстрый вариант:

var datalen = testData.length;
for (var len = 0; len <datalen; len++) {
     total = total + testData[len];
}

Обновление 2:

После тестирования в еще нескольких браузерах этот тестовый сценарий снова принимает другое направление. Только в Chrome и Opera самый быстрый цикл for. В других браузерах путь Shmiddty немного быстрее.

var i = testData.length, sum=0;
while (i--){
    sum += testData[i];
}
12 голосов | спросил Sorskoot 10 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 10 Sep 2012 22:30:14 +0400 2012, 22:30:14

6 ответов


0

Вы также можете сделать цикл следующим образом:

var i = testData.length;

while (i--){
    console.log(testData[i]);
}

Обратите внимание, что он пересекает массив назад .

Или для суммирования:

var i = testData.length, sum=0;

while (i--){
    sum += testData[i];
}
ответил Shmiddty 10 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 10 Sep 2012 22:48:31 +0400 2012, 22:48:31
0

Я бы сказал, что первая форма лучше. Вторая форма имеет некоторые проблемы. Что если у вас есть разреженный массив, содержащий значения 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];
}
ответил Halcyon 10 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 10 Sep 2012 22:32:02 +0400 2012, 22:32:02
0


ОБНОВЛЕНИЕ : я ошибся, 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 . информация.

ответил Oriol 10 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 10 Sep 2012 22:34:22 +0400 2012, 22:34:22
0

Исходя из ответа Шмидта, вы можете использовать цикл в обратном направлении. кажется, что это немного быстрее, чем в обратном направлении в Firefox, и в Chrome они связывают:

var total = 0;
for (var len = testData.length-1; len >=0; len--) {
  total += testData[len];
}

Тест: http://jsperf.com/for-until- длина-против-до-не определено /10

ответил Oriol 10 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 10 Sep 2012 23:32:12 +0400 2012, 23:32:12
0

Что касается производительности, testData[len] просто проверяет, определен ли элемент, а не null /false /"falsish", что быстрее чем сравнение, и особенно получение testData.length для каждой итерации.

Таким образом, второй способ быстрее, но не более надежен - как правильно сказал Фриц ван Кампен.

ответил Simon Forsberg 10 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 10 Sep 2012 22:34:03 +0400 2012, 22:34:03
0

Ваш установочный код вставляет 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- против-до-не определено /6

ответил Diode 10 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 10 Sep 2012 22:49:24 +0400 2012, 22:49:24

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132