Qual é a maneira mais rápida de percorrer uma matriz em JavaScript?

248

Aprendi com os livros que você deve escrever para um loop como este:

for(var i=0, len=arr.length; i < len; i++){
    // blah blah
}

portanto, o valor arr.lengthnão será calculado a cada vez.

Outros dizem que o compilador fará alguma otimização para isso, então você pode simplesmente escrever:

for(var i=0; i < arr.length; i++){
    // blah blah
}

Eu só quero saber qual é a melhor maneira na prática?

wong2
fonte
1
também olhar uma pena quando se lida com variedade looping: jsperf.com/array-loop-var-caching
cloakedninjas
@ wong2 Este benchmark da Browserdiet possui uma coleção mais completa de alternativas.
Domi
1
jsben.ch/#/y3SpC
EscapeNetscape
Aprimorado no jsben anterior: jsben.ch/#/R6LbS
Corbfon
Podemos introduzir o for ... ofloop nesta competição? A sintaxe parece ainda mais fácil que o loop for sem cache, e quero saber se devo mudar para o uso de loops for.
programmerRaj

Respostas:

339

Depois de realizar este teste com os navegadores mais modernos ...

http://jsben.ch/dyM52

Atualmente , a forma mais rápida de loop (e na minha opinião a mais sintaticamente óbvia).

um padrão para loop com cache de comprimento

for (var i = 0, len = myArray.length; i < len; i++) {

}

Eu diria que esse é definitivamente um caso em que aplaudo os desenvolvedores de mecanismos JavaScript. Um tempo de execução deve ser otimizado para maior clareza , não inteligência .

jondavidjohn
fonte
6
Curiosamente, no IE9 este é mais rápido: for (var i = 0, len = myArray.length; i <len; ++ i) {} // prefixo incr, em vez de postfix
Christopher Bennage
4
Consulte Preferir operadores de prefixo sobre postfix para outros motivos para usar ++i.
Bennett McElwee
4
Eu testei usando operador de prefixo como @BennettMcElwee sugerido e ele roda um pouco mais rápido: for(var i=0, len=myArray.length; i<len; ++i) Verifique jsperf.com/caching-array-length/84
victmo
21
Você precisa ter cuidado ao usar esse loop. Comecei a usá-lo e tinha um bug difícil de rastrear por causa de um erro que cometi. Se você aninhar dois loops como este: jsfiddle.net/KQwmL/1 . Você deve ter o cuidado de nomear o var len diferentemente nos dois loops, caso contrário, o segundo loop substituirá o primeiro len.
Rui Marques
6
@WillshawMedia Você pode declarar várias variáveis ​​com uma única varinstrução. Como está escrito, lené realmente definido como você sugere.
precisa saber é o seguinte
90

A maneira mais rápida e absoluta de percorrer uma matriz javascript é:

var len = arr.length;
while (len--) {
    // blah blah
}

Consulte http://blogs.oracle.com/greimer/entry/best_way_to_code_a para obter uma comparação completa

gnur
fonte
1
Não se esqueça de usar var(o outro lense torna uma variável global). Além disso, consulte jsperf.com/loops para obter mais referências de loop.
Mathias Bynens 18/03/11
22
A postagem do blog em que esta resposta se baseia agora tem quase 4 anos e muita coisa mudou nos mecanismos js nesse período. Veja minha resposta abaixo para obter uma comparação atualizada.
precisa saber é o seguinte
1
Eu concordo com @jondavidjohn. Eu testei este código e ele acabou por ser o menos eficiente ... Entrada jsperf.com/caching-array-length/84
victmo
A resposta acima é quase universal (em todos os navegadores) muito mais lenta que um loop for. Veja o link JSPerf na resposta aceita. É uma grande pena, porque é IMO extremamente legível.
Letharion
3
Estou adivinhando @jondavidjohn que o que você quer dizer com 'minha resposta abaixo' é 'minha resposta acima' lol.
Shanimal
40

Em junho de 2016 , fazendo alguns testes no Chrome mais recente (71% do mercado de navegadores em maio de 2016 e aumentando):

  • O loop mais rápido é um loop for , com e sem tamanho de cache, oferecendo desempenho realmente semelhante. (O loop for com comprimento em cache às vezes produzia melhores resultados do que o sem armazenamento em cache, mas a diferença é quase insignificante, o que significa que o mecanismo já pode estar otimizado para favorecer o padrão e provavelmente o mais direto para o loop sem armazenamento em cache).
  • O loop while com decréscimos foi aproximadamente 1,5 vezes mais lento que o loop for.
  • Um loop usando uma função de retorno de chamada (como o padrão forEach), era aproximadamente 10 vezes mais lento que o loop for.

Acredito que esse segmento é muito antigo e é programador enganoso pensar que precisa armazenar em cache o comprimento ou usar movimentos inversos com decréscimos para obter melhor desempenho, escrevendo código menos legível e mais propenso a erros do que um loop simples e direto. Portanto, eu recomendo:

  • Se o seu aplicativo iterar muitos itens ou o código do seu loop estiver dentro de uma função usada com frequência, um loop for direto é a resposta:

    for (var i = 0; i < arr.length; i++) {
      // Do stuff with arr[i] or i
    }
  • Se seu aplicativo realmente não percorre muitos itens ou você só precisa fazer pequenas iterações aqui e ali, o uso do retorno de chamada padrão forEach ou qualquer função semelhante da sua biblioteca JS de escolha pode ser mais compreensível e menos propenso a erros, pois O escopo da variável de índice está fechado e você não precisa usar colchetes, acessando o valor da matriz diretamente:

    arr.forEach(function(value, index) {
      // Do stuff with value or index
    });
  • Se você realmente precisar riscar alguns milissegundos enquanto itera sobre bilhões de linhas e o comprimento da sua matriz não muda durante o processo, considere armazenar em cache o comprimento no loop for. Embora eu ache que isso não seja realmente necessário hoje em dia:

    for (var i = 0, len = arr.length; i < len; i++) {
      // Do stuff with arr[i]
    }
CGodo
fonte
Não. jsbench.github.io/#67b13d4e78cdd0d7a7346410d5becf12 mostra que o mais rápido é "Loop reverso, comparação implícita, código embutido" (105.221 ops / s) enquanto "Loop, valor em cache, código embutido" obteve apenas 76.635 ops / s (Chrome 38.0.2125.111 )
Fr0sT 14/02
@ Fr0sT Seu benchmark é um cenário diferente, percorrendo matrizes do índice 1 para <= comprimento. Claro que isso vai levar a resultados diferentes. Se você tentar percorrer matrizes baseadas em zero com <length - o que me parece ser o cenário usual - você descobrirá que os resultados são melhor otimizados com um loop "for" normal (com o tamanho do cache sendo um pouco mais rápido).
CGodo 27/02
A Kyopaxa alterou os parâmetros de referência para (0 <= i <comprimento), os resultados são os mesmos. "Loop reverso, comparação implícita, chamada de função" marcou 365 kops / s, enquanto "Loop, valor em cache, código embutido" marcou 350 kops / s (FF 51)
Fr0sT
@ Fr0sT se você alterar os for-loops armazenados em cache com base em zero, sem comparação igual, como, por exemplo for(let i=0, j=array.length; i < j; i++), o forward for loops acelera consideravelmente. Em alguns testes que fiz, ele venceu, na maioria, estava dentro da margem de erro ou no loop reverso.
Isaac B
1
@ IsaacB e tudo, desculpe, eu não percebi que o banco está completamente incorreto - todos os loops diretos iteram 1..length enquanto os loops reversos iteram o comprimento..0 (o item arr [length] é inválido). Corrigi os testes e agora eles mostram os seguintes resultados: "Loop, código embutido" 360.616 ops / s ± 0,27%, "Loop, valor em cache, código embutido" 345.786 ops / s ± 2,18% (Sic!) "Loop reverso, comparação implícita, código embutido "322.640 ops / s ± 2,90% (!!!). Os testes foram executados pelo FF51. O novo banco está aqui jsbench.github.io/#6bdfcd2692ba80c16a68c88554281570 . Portanto, parece que não faz sentido uglificar os loops.
Fr0sT
31

Se o pedido não for importante, prefiro este estilo:

for(var i = array.length; i--; )

Ele armazena em cache o comprimento e é muito mais curto para escrever. Mas ele irá percorrer a matriz na ordem inversa.

Felix Kling
fonte
6
Você acabou de matar.
Vignesh Raja
você não precisa de i> = 0 ;?
MarwaAhmad 13/01
3
@MarwaAhmad: No. i--retorna um número e, uma vez que o número é 0a condição, é falseporque Boolean(0) === false.
Felix Kling
30

É só 2018, então uma atualização pode ser legal ...

E eu realmente tenho que discordar da resposta aceita . Adia em diferentes navegadores. alguns fazem forEachmais rápido, outros for-loope alguns while aqui são uma referência em todos os métodos http://jsben.ch/mW36e

arr.forEach( a => {
  // ...
}

e como você pode ver um monte de loop for for(a = 0; ... ), vale a pena mencionar que, sem 'var', as variáveis ​​serão definidas globalmente e isso pode afetar drasticamente a velocidade, tornando-a lenta.

O dispositivo de Duff roda mais rápido na ópera, mas não no firefox

var arr = arr = new Array(11111111).fill(255);
var benches =     
[ [ "empty", () => {
  for(var a = 0, l = arr.length; a < l; a++);
}]
, ["for-loop", () => {
  for(var a = 0, l = arr.length; a < l; ++a)
    var b = arr[a] + 1;
}]
, ["for-loop++", () => {
  for(var a = 0, l = arr.length; a < l; a++)
    var b = arr[a] + 1;
}]
, ["for-loop - arr.length", () => {
  for(var a = 0; a < arr.length; ++a )
    var b = arr[a] + 1;
}]
, ["reverse for-loop", () => {
  for(var a = arr.length - 1; a >= 0; --a )
    var b = arr[a] + 1;
}]
,["while-loop", () => {
  var a = 0, l = arr.length;
  while( a < l ) {
    var b = arr[a] + 1;
    ++a;
  }
}]
, ["reverse-do-while-loop", () => {
  var a = arr.length - 1; // CAREFUL
  do {
    var b = arr[a] + 1;
  } while(a--);   
}]
, ["forEach", () => {
  arr.forEach( a => {
    var b = a + 1;
  });
}]
, ["for const..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( const a in ar ) {
    var b = a + 1;
  }
}]
, ["for let..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( let a in ar ) {
    var b = a + 1;
  }
}]
, ["for var..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( var a in ar ) {
    var b = a + 1;
  }
}]
, ["Duff's device", () => {
  var len = arr.length;
  var i, n = len % 8 - 1;

  if (n > 0) {
    do {
      var b = arr[len-n] + 1;
    } while (--n); // n must be greater than 0 here
  }
  n = (len * 0.125) ^ 0;
  if (n > 0) { 
    do {
      i = --n <<3;
      var b = arr[i] + 1;
      var c = arr[i+1] + 1;
      var d = arr[i+2] + 1;
      var e = arr[i+3] + 1;
      var f = arr[i+4] + 1;
      var g = arr[i+5] + 1;
      var h = arr[i+6] + 1;
      var k = arr[i+7] + 1;
    }
    while (n); // n must be greater than 0 here also
  }
}]];
function bench(title, f) {
  var t0 = performance.now();
  var res = f();
  return performance.now() - t0; // console.log(`${title} took ${t1-t0} msec`);
}
var globalVarTime = bench( "for-loop without 'var'", () => {
  // Here if you forget to put 'var' so variables'll be global
  for(a = 0, l = arr.length; a < l; ++a)
     var b = arr[a] + 1;
});
var times = benches.map( function(a) {
                      arr = new Array(11111111).fill(255);
                      return [a[0], bench(...a)]
                     }).sort( (a,b) => a[1]-b[1] );
var max = times[times.length-1][1];
times = times.map( a => {a[2] = (a[1]/max)*100; return a; } );
var template = (title, time, n) =>
  `<div>` +
    `<span>${title} &nbsp;</span>` +
    `<span style="width:${3+n/2}%">&nbsp;${Number(time.toFixed(3))}msec</span>` +
  `</div>`;

var strRes = times.map( t => template(...t) ).join("\n") + 
            `<br><br>for-loop without 'var' ${globalVarTime} msec.`;
var $container = document.getElementById("container");
$container.innerHTML = strRes;
body { color:#fff; background:#333; font-family:helvetica; }
body > div > div {  clear:both   }
body > div > div > span {
  float:left;
  width:43%;
  margin:3px 0;
  text-align:right;
}
body > div > div > span:nth-child(2) {
  text-align:left;
  background:darkorange;
  animation:showup .37s .111s;
  -webkit-animation:showup .37s .111s;
}
@keyframes showup { from { width:0; } }
@-webkit-keyframes showup { from { width:0; } }
<div id="container"> </div>

nullqube
fonte
3
@Maykonn você provavelmente quis dizer "e funciona em todos os lugares, mas Opera Mini"
dube
3
@ Maykonn, que não está listado na exibição padrão, porque 0,18% de todos os usuários têm o IE8 e você não deve perder tempo tentando apoiá-lo; em 2018 é um cavalo morto.
dube
1
Definitivamente, é verdade se você considerar todos os usuários em todo o mundo. Mas, infelizmente, em partes específicas do mundo, o IE8 ainda é relevante.
Maykonn 27/08/19
1
Se eu puder, não apenas navegadores diferentes terão resultados diferentes com métodos diferentes, mas os mesmos navegadores terão resultados diferentes com entradas diferentes. Uma enorme Matriz de número único será muito otimizada, enquanto uma pequena mista não.
Kaiido
1
@Tahlil Thanks.
Nulo19
19

2014 Whileestá de volta

Apenas pense lógico.

Veja isso

for( var index = 0 , length = array.length ; index < length ; index++ ) {

 //do stuff

}
  1. Precisa criar pelo menos 2 variáveis ​​(índice, comprimento)
  2. Precisa verificar se o índice é menor que o comprimento
  3. Precisa aumentar o índice
  4. o forloop tem 3 parâmetros

Agora me diga por que isso deve ser mais rápido do que:

var length = array.length;

while( --length ) { //or length--

 //do stuff

}
  1. Uma variável
  2. Sem verificações
  3. o índice diminui (as máquinas preferem isso)
  4. while tem apenas um parâmetro

Fiquei totalmente confuso quando o Chrome 28 mostrou que o loop for é mais rápido do que o tempo. Isso deve ter ben algum tipo de

"Todo mundo está usando o loop for, vamos nos concentrar nisso ao desenvolver para o chrome".

Mas agora, em 2014, o loop while está de volta no chrome. é 2 vezes mais rápido, em outros navegadores / antigos sempre foi mais rápido.

Ultimamente eu fiz alguns novos testes. Agora, no ambiente real, esses códigos curtos não valem nada e o jsperf não pode realmente executar corretamente o loop while, porque precisa recriar o array.length que também leva tempo.

você não pode obter a velocidade real de um loop while no jsperf.

você precisa criar sua própria função personalizada e verificar com window.performance.now()

E sim ... não há como o loop while ser simplesmente mais rápido.

O verdadeiro problema é, na verdade, o tempo de manipulação / renderização / tempo de desenho ou como você quiser chamá-lo.

Por exemplo, eu tenho uma cena de tela em que preciso calcular as coordenadas e colisões ... isso é feito entre 10-200 MicroSegundos (não milissegundos). na verdade, leva vários milissegundos para renderizar tudo.

MAS

Existe outra maneira de super desempenho usando o for loopem alguns casos ... por exemplo, para copiar / clonar uma matriz

for(
 var i = array.length ;
 i > 0 ;
 arrayCopy[ --i ] = array[ i ] // doing stuff
);

Observe a configuração dos parâmetros:

  1. Igual ao loop while, estou usando apenas uma variável
  2. Precisa verificar se o índice é maior que 0;
  3. Como você pode ver, essa abordagem é diferente do loop for normal que todo mundo usa, como eu faço coisas dentro do terceiro parâmetro e também diminuo diretamente dentro da matriz.

Disse que isso confirma que máquinas como a -

escrevendo que eu estava pensando em torná-lo um pouco mais curto e remover algumas coisas inúteis e escrevi este usando o mesmo estilo:

for(
 var i = array.length ;
 i-- ;
 arrayCopy[ i ] = array[ i ] // doing stuff
);

Mesmo que seja mais curto, parece que usar imais uma vez torna tudo mais lento. É 1/5 mais lento que o forloop anterior e o anterior while.

Nota: o ;é muito importante depois do looo sem{}

Mesmo se eu apenas lhe disser que o jsperf não é a melhor maneira de testar scripts ... eu adicionei esses 2 loops aqui

http://jsperf.com/caching-array-length/40

E aqui está outra resposta sobre o desempenho em javascript

https://stackoverflow.com/a/21353032/2450730

Esta resposta é para mostrar maneiras eficientes de escrever javascript. Portanto, se você não conseguir ler isso, pergunte e você receberá uma resposta ou lerá um livro sobre javascript http://www.ecma-international.org/ecma-262/5.1/

cocco
fonte
Esta resposta começa de muito bom . Notei que nos últimos dois anos a forvelocidade foi mais rápida que a while, e uma vez li no crome-dev que foi exatamente por causa do motivo que você mencionou. Seria apenas uma questão de tempo antes de whilerecuperar o atraso. A partir desse momento, a lógica da primeira parte da sua resposta se manterá (mais uma vez, sim)! No entanto, as implementações modernas não seguem mais rigidamente todas as etapas especificadas pelo ecma (elas otimizam). Como agora seu motor não é mais o gargalo mais perceptível, agora é possível notar os erros de cache da CPU em loops reversos !
GitaarLAB 17/03/2015
Explique, então talvez eu possa corrigir a resposta ou aprender algo novo. btw, a resposta é agora mais do que um ano de idade ... navegadores podem ter mudado ao longo do tempo, como sempre fazem ...
Cocco
Na minha opinião, enquanto (--length) é mau, porque enquanto tecnicamente funciona porque 0 é falso, 0 e falso não são realmente a mesma coisa semântica.
scott.korin
sim ... é um post antigo agora ... mas sim, eu amo a simplicidade de um tempo. E com certeza, como você mencionou nos dois casos, você precisa saber o que escrever. Por outro lado, nunca tive a necessidade de repetir números negativos.
Cocco
9
"máquinas preferem este" soa como uma frase de um anúncio de um detergente para a roupa
CocoaBean
11

http://jsperf.com/caching-array-length/60

A última revisão do teste, que eu preparei (reutilizando um antigo), mostra uma coisa.

O comprimento do cache não é muito importante, mas não prejudica.

Toda primeira execução do teste acima (na aba recém-aberta) fornece os melhores resultados para os últimos 4 trechos (3º, 5º, 7º e 10º nos gráficos) no Chrome, Opera e Firefox no meu Debian Squeeze de 64 bits ( meu hardware de desktop) ) Execuções subseqüentes fornecem resultados bastante diferentes.

As conclusões em termos de desempenho são simples:

  • Vá com loop for (forward) e teste usando em !==vez de <.
  • Se você não precisar reutilizar a matriz posteriormente, o loop while com comprimento decrescente e a shift()matriz destrutiva também serão eficientes.

tl; dr

Atualmente (2011.10) abaixo do padrão parece ser o mais rápido.

for (var i = 0, len = arr.length; i !== len; i++) {
    ...
}

Lembre-se de que o cache arr.lengthnão é crucial aqui, então você pode apenas testar i !== arr.lengthe o desempenho não será reduzido, mas você obterá um código mais curto.


PS: Eu sei que no snippet com shift()seu resultado poderia ser usado em vez de acessar o 0º elemento, mas de alguma forma esqueci que, depois de reutilizar a revisão anterior (que apresentava mal os loops), e mais tarde eu não queria perder os resultados já obtidos.

przemoc
fonte
Criar variável dentro do loop como let current = arr [i] pode reduzir um desempenho (grande alocação de memória)? Ou seria melhor declarar corrente antes do loop? Ou use arr [i] em todos os lugares dentro do loop?
Makarov Sergey
8

"Melhor" como no desempenho puro? ou desempenho E legibilidade?

O desempenho puro "melhor" é esse, que usa um cache e o operador de prefixo ++ (meus dados: http://jsperf.com/caching-array-length/189 )

for (var i = 0, len = myArray.length; i < len; ++i) {
  // blah blah
}

Eu argumentaria que o loop for sem cache é o melhor equilíbrio entre tempo de execução e tempo de leitura do programador. Todo programador que iniciou com C / C ++ / Java não perde um ms tendo que ler este

for(var i=0; i < arr.length; i++){
  // blah blah
}
valbaca
fonte
2
+1 para facilitar a leitura. Não importa o quão bem lenseja nomeado, é preciso sempre fazer uma análise dupla do primeiro loop. A intenção do segundo ciclo é óbvia.
22413 Josh Johnson
7

** em cache o comprimento da matriz dentro do loop, alguns segundos serão iludidos. Depende dos itens da matriz, se houver mais itens na matriz, haverá uma grande diferença em relação a Ms de tempo *

**

sArr; //Array[158];

for(var i = 0 ; i <sArr.length ; i++) {
 callArray(sArr[i]); //function call
}

***end: 6.875ms***

**

**

sArr; //Array[158];
for(var i = 0,len = sArr.length ; i < len ; i++) {
  callArray(sArr[i]); //function call
}

***end: 1.354ms***

**

Shushanth Pallegar
fonte
6

Este parece ser o caminho mais rápido de longe ...

var el;
while (el = arr.shift()) {
  el *= 2;
}

Leve em consideração que isso consumirá a matriz, a comerá e não deixará nada ...

Sergio
fonte
2
arr.shift();em vez de arr.pop() evitar que o inverso da matriz seja evitado.
Tintu C Raju 22/10/2015
1
@Gargaroz se você estiver recebendo um JSON de um serviço da web, por exemplo, um serviço de bate-papo ou itens em um catálogo de produtos. Outra situação em que você só precisa usar a matriz uma vez pode ser, por exemplo, um gráfico que obtém muitas coordenadas em intervalos. Existem muitos exemplos.
18716 Sergio Sergio
Legal, obrigado pela explicação, muito gentil da sua parte; você pode me indicar a direção em que posso encontrar mais exemplos para explorar esse tipo de loop?
Gargaroz
1
Actualmente no Chrome 53 e Firefox 48 é um dos abordagem mais lenta - verificação sobre perfjs.info/array-iteration
Pencroff
1
@Alireza concorda, eu tenho um comentário para isso na minha resposta também.
Sergio
4

É o ano de 2017 .

Eu fiz alguns testes.

https://jsperf.com/fastest-way-to-iterate-through-an-array/

Parece que o whilemétodo é o mais rápido no Chrome.

Parece que o decréscimo esquerda ( --i) é muito mais rápido do que os outros ( ++i, i--, i++) no Firefox.

Essa abordagem é o jejum em média. Mas itera a matriz em ordem inversa.

let i = array.length;
while (--i >= 0) {
    doSomething(array[i]);
}

Se a ordem futura for importante, use esta abordagem.

let ii = array.length;
let i = 0;
while (i < ii) {
    doSomething(array[i]);
    ++i;
}
SeregPie
fonte
3
Usando a palavra let- chave, você está realmente comparando o desempenho da criação do escopo ao invés do desempenho do loop. O uso let i = 0, ii = array.lengthem seus forloops criará um novo escopo para essas variáveis ​​dentro do forbloco. Seus whileexemplos não criam um novo escopo para as variáveis ​​dentro do whilebloco e é por isso que elas são mais rápidas. Se você usar em varvez dos letloops for, verá como os loops ainda são tão rápidos quanto os de 2017, mas são mais legíveis.
precisa saber é
Aqui está uma JSPerf do que estou falando: jsperf.com/javascript-loop-testing-let-vs-var
CGodo
Este é apenas um problema no Chrome. Em outros navegadores vare letcom o mesmo desempenho - stackoverflow.com/a/32345435/1785975
SeregPie
Interessante. De qualquer forma, não acho a afirmação de " whileser mais rápido no Chrome". É apenas se estiver usando letdevido a problemas de desempenho dessa palavra-chave no Chrome. Se você estiver usando varou com outros navegadores fore whilefor praticamente o mesmo, às vezes foré ainda mais rápido, dependendo do benchmark, e é mais compacto e legível.
CGodo
2

Eu sempre escrevo no primeiro estilo.

Mesmo que um compilador seja inteligente o suficiente para otimizá-lo para matrizes, mas ainda assim se estiver usando o DOMNodeList aqui ou algum objeto complicado com comprimento calculado?

Sei qual é a pergunta sobre matrizes, mas acho que é uma boa prática escrever todos os seus loops em um estilo.

Olegas
fonte
1
var arr = []; // The array
var i = 0;
while (i < arr.length) {
    // Do something with arr[i]
    i++;
}

i ++ é mais rápido que ++ i, --i e i--

Além disso, você pode salvar a última linha fazendo arr [i ++] na última vez que precisar acessar i (mas isso pode ser difícil de depurar).

Você pode testá-lo aqui (com outros testes de loop): http://jsperf.com/for-vs- whilepop/5

Forestrf
fonte
1
Actualmente no Chrome 53, é verdade, mas o Firefox 48 tem a mesma velocidade - controlo sobre perfjs.info/array-iteration
Pencroff
thunderguy.com/semicolon/2002/08/13/… diz que ++ié mais rápido ...
IMTheNachoMan
1

Em setembro de 2017, esses testes jsperf mostraram o seguinte padrão com melhor desempenho no Chrome 60:

function foo(x) {
 x;
};
arr.forEach(foo);

Alguém é capaz de se reproduzir?

John Vandivier
fonte
Sim, parece ser o mais rápido. No entanto, tente executar isso no IE11 e essas opções são as mais lentas. E no Firefox 55.03, o 'velho lençol em cache quebrado' está chegando a 12mil, um desempenho impressionante comparado aos 3,3k do chrome. Para ter um desempenho consistente em todos os navegadores, você deve usar o loop médio mais rápido para todos os navegadores.
Plippie
0

Eu tentei algumas outras maneiras de iterar uma matriz enorme e descobri que reduzir pela metade o comprimento da matriz e depois iterar as duas metades em um único loop é mais rápido. Essa diferença de desempenho pode ser vista durante o processamento de grandes matrizes .

var firstHalfLen =0;
var secondHalfLen = 0;
var count2=0;
var searchterm = "face";
var halfLen = arrayLength/2;
if(arrayLength%2==halfLen)
{
   firstHalfLen = Math.ceil(halfLen);
   secondHalfLen=Math.floor(halfLen);
}
else
{
   firstHalfLen=halfLen;
   secondHalfLen=halfLen;
}
for(var firstHalfCOunter=0,secondHalfCounter = arrayLength-secondHalfLen;
    firstHalfCOunter < firstHalfLen;
    firstHalfCOunter++)
{
  if(mainArray[firstHalfCOunter].search(new RegExp(searchterm, "i"))> -1)
  {
    count2+=1;
  }
  if(secondHalfCounter < arrayLength)
  {
    if(mainArray[secondHalfCounter].search(new RegExp(searchterm, "i"))> -1)
    {
        count2+=1;
    }
    secondHalfCounter++; 
  }
}

Alguma comparação de desempenho (usando timer.js) entre o comprimento em cache do loop VS o método acima.

http://jsfiddle.net/tejzpr/bbLgzxgo/

tejzpr
fonte
0

Outro teste do jsperf.com: http://jsperf.com/ while-reverse-vs-for-cached-length

O loop while reverso parece ser o mais rápido. O único problema é que enquanto (--i) irá parar em 0. Como posso acessar o array [0] no meu loop?

Moritz Schmitz v. Hülst
fonte
2
Se você o fizer while (i--), a veracidade de iserá testada antes de diminuir, em vez de diminuir e, em seguida, testar a veracidade.
Justin Fisher
0

O loop while é um pouco mais rápido que o loop for.

var len = arr.length;
while (len--) {
    // blah blah
}

Use o loop while

Azhar Zafar
fonte
-1

A solução mais elegante que conheço é usar o mapa.

var arr = [1,2,3];
arr.map(function(input){console.log(input);});
Dan
fonte
46
A questão não está pedindo a forma mais lenta para percorrer um loop
eoleary
-1

Tente o seguinte:

var myarray =[],
i = myarray.lenght;
while(i--){
// do somthing
}
li bing zhao
fonte
-1

A maneira mais rápida de fazer um loop em uma matriz é usando o filtro. O método filter () cria uma nova matriz com todos os elementos que passam no teste implementado pela função fornecida.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

const words = ['Floccinaucinihilipilification', 'limit', 'elite', 'Hippopotomonstrosesquipedaliophobia', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(new Date(), result);

Pela minha experiência, eu sempre prefiro filtros, mapas etc.

Rigin Oommen
fonte
A questão é iterar sobre a matriz no menor tempo possível, sem copiar a matriz para uma nova matriz.
Rahul Kadukar
-1

A partir de 2019, o WebWorker tornou-se mais popular; para grandes conjuntos de dados, podemos usar o WebWorker para processar muito mais rapidamente, utilizando totalmente os processadores com vários núcleos.

Também temos o Parallel.js, que facilita o uso do WebWorker no processamento de dados.

Stackia
fonte