Как лучше всего делать циклы в JavaScript - PullRequest
28 голосов
/ 11 октября 2008

Я наткнулся на несколько методов зацикливания в JavaScript, что мне больше всего нравится:

for(var i = 0; i < a.length; i++){
    var element = a[i];
}

Но, как проверено здесь (http://www.robertnyman.com/2008/04/11/javascript-loop-performance/),, это, вероятно, следует записать так, чтобы длина рассчитывалась только один раз.

В jQuery есть .each, в котором вы можете прикрепить функцию. Мне это нравится немного лучше, потому что мне не нужно вводить массив дважды, как в приведенном выше решении.

Если бы JavaScript поддерживал макросы, это было бы просто, если бы вы сами катались, но, к сожалению, это не так.

Так что вы, ребята, используете?

Ответы [ 9 ]

36 голосов
/ 11 октября 2008

Я начал использовать итераторы, где это уместно. Производительность является разумной, но, что более важно, она позволяет инкапсулировать циклическую логику:

function createIterator(x) {
    var i = 0;

     return function(){
       return x[i++];
    };
}

Затем использовать:

var iterator=createIterator(['a','b','c','d','e','f','g']);

iterator();

возвращает «а»;

iterator();

возвращает "b";

и т. Д.

Для просмотра всего списка и отображения каждого элемента:

var current;

while(current=iterator())
{
    console.log(current);
}

Имейте в виду, что вышеприведенное допустимо только для итерации списка, который содержит «не ложные» значения. Если этот массив содержал любое из:

  • 0
  • ложь
  • ""
  • 1026 * нуль *
  • NaN

предыдущий цикл остановился бы на этом элементе, а не всегда на том, что вы хотите / ожидаете.

Чтобы избежать этого, используйте:

var current;

while((current=iterator())!==undefined)
{
   console.log(current);
}
10 голосов
/ 11 октября 2008

Небольшое улучшение по сравнению с оригиналом, для расчета размера массива только один раз:

for(var i = 0, len = a.length; i < len; i++){ var element = a[i]; }

Кроме того, я вижу много петель. Хотя имейте в виду, что это технически не кошерно и будет вызывать проблемы именно с Prototype:

for (i in a) { var element = a[i]; }
6 голосов
/ 14 октября 2008

Я знаю, что опоздал на вечеринку, но я использую обратные циклы для циклов, которые не зависят от порядка

Очень похоже на @Mr. Ондатра - но упрощает тест:

var i = a.length, element = null;
while (i--) {
  element = a[i];
}
6 голосов
/ 11 октября 2008

Сначала сохраните длину в переменной.

  var len = a.length;
  for (var i = 0; i < len; i++) {
    var element = a[i];
  }
2 голосов
/ 11 октября 2008

Вы всегда можете просто использовать цикл while и вычислить предел массива до того, как получите.

Var max = a.length-1;
var i = 0;

while(i <= max)
{
var element = a[i];
i++;
}
1 голос
/ 12 октября 2008

Я не пользуюсь им сам, но один из моих коллег использует этот стиль:

var myArray = [1,2,3,4];
for (var i = 0, item; item = myArray[i]; ++i) {
    alert(item);
}

как и ответ Эша, это вызовет проблемы, если в вашем массиве есть значения "falsey". Чтобы избежать этой проблемы, измените его на (item = myArray[i]) != undefined

1 голос
/ 11 октября 2008

Если у вас много элементов в массиве, а скорость - это проблема, то вы хотите использовать цикл while, который повторяется от наивысшего к наименьшему.

  var i = a.length;
  while( --i >= 0 ) {
    var element = a[i];
    // do stuff with element
  }  
0 голосов
/ 08 января 2009

Я не вижу, в чем проблема использования стандартного цикла for (;;). Маленький тест

var x;
var a = [];
// filling array
var t0 = new Date().getTime();
for( var i = 0; i < 100000; i++ ) {
    a[i] = Math.floor( Math.random()*100000 );
}

// normal loop
var t1 = new Date().getTime();
for( var i = 0; i < 100000; i++ ) {
    x = a[i];
}

// using length
var t2 = new Date().getTime();
for( var i = 0; i < a.length; i++ ) {
    x = a[i];
}

// storing length (pollution - we now have a global l as well as an i )
var t3 = new Date().getTime();
for( var i = 0, l = a.length; i < l; i++ ) {
    x = a[i];
}

// for in
var t4 = new Date().getTime();
for( var i in a ) {
    x = a[i];
}

// checked for in
var t5 = new Date().getTime();
for( var i in a ) {
    if (a.hasOwnProperty(i)) {
        x = a[i];
    }
}

var t6 = new Date().getTime();
var msg = 'filling array: '+(t1-t0)+'ms\n'+
          'normal loop: '+(t2-t1)+'ms\n'+
          'using length: '+(t3-t2)+'ms\n'+
          'storing length: '+(t4-t3)+'ms\n'+
          'for in: '+(t5-t4)+'ms\n'+
          'checked for in: '+(t6-t5)+'ms';
console.log( msg );

Результат:

filling array: 227ms
normal loop: 21ms
using length: 26ms
storing length: 24ms 
for in: 154ms
checked for in: 176ms

Итак: - для получения самого длинного, использование свойства length (которое является свойством и его не нужно вычислять) почти так же быстро, как и его первое сохранение - что только на усы медленнее, чем использование целого числа.
И a for () - это обычный способ зацикливания массива, который все ожидают и понимают.

Все они добавляют переменную в область действия, в которой они запускаются - i - это общее название для этого использования и поэтому не должно использоваться для других целей. Сохранение длины сначала добавляет еще одну переменную - l - в область видимости, которая не нужна

0 голосов
/ 07 января 2009

Итак, сначала вы определите идеальный цикл javascript, я думаю, он должен выглядеть следующим образом:

ary.each (function () {$ arguments [0]). Remove ();})

Для этого может потребоваться библиотека prototype.js.

Далее, вы не согласны с аргументами [0] и получаете код, автоматически генерируемый из вашей серверной среды. Это работает, только если лестница - Приморская.

Теперь у вас есть вышеприведенное, сгенерированное:

все делают: [: each | каждый элемент удалить].

Он поставляется с завершением синтаксиса и в точности соответствует приведенному выше JavaScript. И это заставит людей вращаться, которые раньше не использовали интеграцию прототипов побережья, когда они читают ваш код. Это, конечно, заставляет вас чувствовать себя крутым тоже. Не говоря уже о выигрыше в гикизме, который вы можете получить здесь. Девушкам это нравится!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...