Para cada um através de um array em JavaScript?
Como posso fazer um loop através de todas as entradas de um array usando JavaScript?
Pensei que fosse algo assim.forEach(instance in theArray)
Onde theArray
está a minha matriz, mas isto parece estar incorrecto.
28 answers
TL; DR
- Não utilize
for-in
a não ser que o utilize com salvaguardas ou esteja pelo menos ciente do motivo pelo qual o pode morder. - As suas melhores apostas são normalmente ...
JavaScript tem uma semântica poderosa para looping através de arrays e objetos do tipo array. Eu dividi a resposta em duas partes: opções para arrays genuínos, e opções para coisas que são apenas array-como, como o Objeto arguments
, outros objetos iteráveis (ES2015+), coleções DOM, e assim por diante.
Para Matrizes Reais
Você tem três opções em ECMAScript 5 ("ES5"), a versão mais amplamente suportado no momento, e mais duas adicionado em ECMAScript 2015 ("ES2015", "ES6"):
- utilizar
forEach
e produtos afins (ES5+) - usa um simples
for
laço -
for-in
correctamente - utilizar
for-of
(utilizar implicitamente um iterador) (ES2015+) - utilizar explicitamente um iterador (ES2015+)
Detalhes:
1. Utilizar forEach
e
Em qualquer vagamente-ambiente moderno (assim, não IE8) onde você tem acesso à Array
recursos adicionados por ES5 (diretamente ou utilizando livros), você pode usar forEach
(spec
| MDN
):
var a = ["a", "b", "c"];
a.forEach(function(entry) {
console.log(entry);
});
forEach
aceita uma função de callback e, opcionalmente, um valor a usar como this
ao invocar essa chamada (não usada acima). O callback é chamado para cada entrada na matriz, em ordem, saltando entradas inexistentes em arrays esparsos. Embora eu só tenha usado um argumento acima, o callback é chamado com três: o valor de cada entrada, o índice desse item, e uma referência ao array que você está iterando (no caso de sua função ainda não ter it handy).
A menos que esteja a apoiar navegadores obsoletos como o IE8 (que o NetApps mostra com uma quota de mercado de pouco mais de 4% a partir desta escrita em setembro de 2016), pode utilizar com prazer {[[30]} numa página web de uso geral sem um shim. Se você precisar de suportar navegadores obsoletos, shimming/polifilling forEach
é fácil de fazer (procurar por "es5 shim" para várias opções).
forEach
tem o benefício que você não tem que declarar variáveis de indexação e valor no âmbito de containing, como eles são fornecidos como argumentos para a função de iteração, e tão bem escopo para apenas essa iteração.
Se você está preocupado com o custo de execução de fazer uma chamada de função para cada entrada de array, não seja; detalhes.
Além disso, forEach
é a função "loop through them all" , mas o ES5 definiu várias outras funções úteis "trabalhar o seu caminho através do array e fazer coisas", incluindo:
-
every
(pára de rodar da primeira vez o callback devolvefalse
ou algo do género falsey) -
some
(pára de repetir a primeira vez que o callback retornatrue
ou algo truthy) -
filter
(cria uma nova lista, incluindo os elementos onde a função do filtro devolvetrue
e omite os que devolvefalse
) -
map
(cria uma nova lista a partir dos valores devolvidos pelo callback) -
reduce
(constrói um valor repetidamente chamando o callback, passando em valores anteriores; veja a especificação para os detalhes; útil para somar o conteúdo de uma matriz e muitas outras coisas) -
reduceRight
(comoreduce
, mas funciona em ordem descendente em vez de ascendente)
2. Usar um simples for
loop
Às vezes, os velhos costumes são os melhores.
var index;
var a = ["a", "b", "c"];
for (index = 0; index < a.length; ++index) {
console.log(a[index]);
}
Se o comprimento do array não mudar durante o loop, e está em código sensível ao desempenho( improvável), um pouco mais uma versão complicada a agarrar o comprimento à frente pode ser um minúsculo um pouco mais rápido:
var index, len;
var a = ["a", "b", "c"];
for (index = 0, len = a.length; index < len; ++index) {
console.log(a[index]);
}
E / ou contagem regressiva:
var index;
var a = ["a", "b", "c"];
for (index = a.length - 1; index >= 0; --index) {
console.log(a[index]);
}
Mas com motores JavaScript modernos, é raro ter de tirar aquele último pedaço de sumo.
Em ES2015 ou mais, você pode tornar as suas variáveis de índice e valor locais para o laço for
:
let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
let value = a[index];
}
//console.log(index); // Would cause "ReferenceError: index is not defined"
//console.log(value); // Would cause "ReferenceError: value is not defined"
E quando você faz isso, não só value
mas também index
é recriado para cada iteração de laço, o que significa os encerramentos criados no corpo do laço mantêm uma referência ao index
(e value
) criado para essa iteração específica:
let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
divs[index].addEventListener('click', e => {
alert("Index is: " + index);
});
}
Se tivesses cinco divs, terias "índice é: 0" se clicasses no primeiro e "índice é: 4" se clicasses no último. Isto não funcionase usar var
em vez de let
.
3. Utilização for-in
correctamente
As pessoas dizem-te para usares for-in
, mas não é para isso que for-in
serve. Loops através das propriedades enumeráveis de um objeto , não os índices de uma matriz. a ordem não está garantida, nem mesmo nos ES2015 (ES6). ES2015 definir uma ordem para propriedades de objeto (via [[OwnPropertyKeys]]
, [[Enumerate]]
, e as coisas que usá-los como Object.getOwnPropertyKeys
), mas não definir que for-in
vai seguir essa ordem. (Pormenores em esta outra resposta .)
// `a` is a sparse array
var key;
var a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (key in a) {
if (a.hasOwnProperty(key) && // These are explained
/^0$|^[1-9]\d*$/.test(key) && // and then hidden
key <= 4294967294 // away below
) {
console.log(a[key]);
}
}
Note os dois controlos:
Que o objecto tem a sua propriedade própria por esse nome (não uma que herde do seu protótipo), e
Que a chave é uma cadeia numérica base-10 em sua forma de cadeia normal e seu valor é no caderno de especificações . Outros números (não inteiros, números negativos, números superiores a 2^32-2) não são índices de matriz. A razão é 2^32 - 2 é que isso faz com que o maior valor de índice um menor do que 2^32 - 1, que é o valor máximo que um array
length
pode ter. (Por exemplo, o comprimento de uma matriz encaixa em um número inteiro sem sinal de 32 bits.(Props to RobG for pointing out in a comment on my blog post that my previous test was not quite direito.)
Isso é um pequeno pedaço de adicional por iteração de loop na maioria das matrizes, mas se você tem um array esparse , ele pode ser uma maneira mais eficiente de loop porque ele só loops para entradas que realmente existem. Por exemplo, para o array acima, nós fazemos um loop de um total de três vezes (para chaves "0"
, "10"
, e lembrem-se, são cordas, não 10.001 vezes.
function arrayHasOwnIndex(array, prop) {
return array.hasOwnProperty(prop) && /^0$|^[1-9]\d*$/.test(prop) && prop <= 4294967294; // 2^32 - 2
}
E depois usávamos assim:
for (key in a) {
if (arrayHasOwnIndex(a, key)) {
console.log(a[key]);
}
}
Ou se você está interessado em apenas um teste "bom o suficiente para a maioria dos casos", você poderia usar isso, mas enquanto está perto, não é completamente correto:
for (key in a) {
// "Good enough" for most cases
if (String(parseInt(key, 10)) === key && a.hasOwnProperty(key)) {
console.log(a[key]);
}
}
4. Use for-of
(utilizar implicitamente um iterador) (ES2015+)
ES2015 adiciona iteradores ao JavaScript. A maneira mais fácil de usar iteradores é a nova declaração for-of
. Parece que isto:
var val;
var a = ["a", "b", "c"];
for (val of a) {
console.log(val);
}
Resultado:
a b cDebaixo das capas, fica um iterador do array e passa por ele, obtendo os valores a partir dele. Isto não tem o problema que o uso de
for-in
tem, porque ele usa um iterador definido pelo objeto (o array), e arrays definem que seus iteradores iterate através de suas entradas (Não suas propriedades). Ao contrário de for-in
em ES5, a ordem em que as entradas são visitadas é a ordem numérica das suas Index.
5. Utilizar explicitamente um iterador (ES2015+)
Às vezes, é melhor usar um iterador explicitamente. Você também pode fazer isso, embora seja muito mais complicado do que for-of
. Parece isto:
var a = ["a", "b", "c"];
var it = a.values();
var entry;
while (!(entry = it.next()).done) {
console.log(entry.value);
}
O iterador é um objecto que corresponde à definição do iterador na especificação. O seu método next
devolve um novo objectode resultado de cada vez que lhe chamas. O objeto do resultado tem uma propriedade, done
, dizendo-nos se está feito, e um propriedade value
com o valor para essa iteração. (done
é opcional se for false
, value
é opcional se for undefined
.)
O Significado de value
varia de acordo com o iterador; as matrizes suportam (pelo menos) três funções que devolvem iteradores:
-
Este é o que usei acima. Devolve um iterador onde cada
value
é o item da lista para essa iteração ("a"
,"b"
, e"c"
no exemplo anterior). -
keys()
: Devolve um iterador onde cadavalue
é a chave para que a iteração (para o nossoa
acima, que seria"0"
, então"1"
, então"2"
). -
entries()
: Devolve um iterador onde cadavalue
é um array na forma[key, value]
para essa iteração.
Para Objectos De Matriz
Além de matrizes verdadeiras, existem também array-like objectos que têm uma length
propriedade e propriedades com nomes numéricos: NodeList
instâncias, o objecto arguments
, etc. Como vamos vasculhar o conteúdo deles?
Utilize qualquer uma das opções acima para arrays
Pelo menos alguns, e possivelmente a maioria ou até mesmo todos, das aproximações do array acima frequentemente se aplicam igualmente bem aos objetos do tipo array:
-
Uso
forEach
e afins (ES5+)As várias funções em
Array.prototype
são "intencionalmente genéricas" e podem normalmente ser usadas em objectos de matriz viaFunction#call
ouFunction#apply
. (Ver a secção 4. 4). ressalva para objetos fornecidos pelo hospedeiro no final desta resposta, mas é um problema raro.)Suponha que queria usar
forEach
numa propriedadeNode
'SchildNodes
. Tu farias isto.Array.prototype.forEach.call(node.childNodes, function(child) { // Do something with `child` });
Se você vai fazer isso muito, você pode querer pegar uma cópia da referência da função em uma variável para reutilização, por exemplo:
// (This is all presumably in some scoping function) var forEach = Array.prototype.forEach; // Then later... forEach.call(node.childNodes, function(child) { // Do something with `child` });
-
Usar um simples laço
for
Obviamente, um simples laço
for
aplica-se ao array-like objecto. -
Utilização
for-in
correctamentefor-in
com as mesmas salvaguardas que com um array deve trabalhar com objetos do tipo array também; a advertência para os objetos fornecidos pelo host em #1 acima pode ser aplicada. -
Use
for-of
(utilizar implicitamente um iterador) (ES2015+)for-of
usará o iterador fornecido pelo objeto (se existir); teremos que ver como isso joga com os vários objetos array-like, especialmente as que recebem hospedeiros. Por exemplo, a especificação para oNodeList
dequerySelectorAll
foi atualizada para suportar a iteração. A especificação para oHTMLCollection
degetElementsByTagName
não era. -
Utilizar explicitamente um iterador (ES2015+)
4, Temos de ver como os iteradores funcionam.
Outras vezes, você pode querer converter um objeto array em um array verdadeiro. Fazer isso é surpreendentemente fácil:
-
Use o
slice
método das matrizesNós podemos usar o método
slice
de matrizes, que como os outros métodos mencionados acima é "intencionalmente genérico" e assim pode ser usado com objetos do tipo matriz, como este:
Então, por exemplo, se quisermos converter umvar trueArray = Array.prototype.slice.call(arrayLikeObject);
NodeList
em uma matriz verdadeira, podemos fazer isso:var divs = Array.prototype.slice.call(document.querySelectorAll("div"));
Ver a Caveat para os objectos fornecidos pela máquina abaixo. Em especial, nota que isto vai falhar no IE8 e antes, que não te deixam usar objectos fornecidos pelo host como
this
assim. -
Também é possível usar a sintaxe de spread do ES2015 com motores JavaScript que suportam esta funcionalidade:
var trueArray = [...iterableObject];
Então, por exemplo, se quisermos converter um
NodeList
em uma matriz verdadeira, com a sintaxe de spread isto torna-se bastante sucinto:var divs = [...document.querySelectorAll("div")];
-
Utilização
Array.from
(spec) | (MDN)Array.from
(ES2015+, mas facilmente polifilada) cria um array a partir de um objeto array-like, opcionalmente passando as entradas através de uma função de mapeamento primeiro. Então:var divs = Array.from(document.querySelectorAll("div"));
Ou se quisesse obter uma lista dos nomes das marcas dos elementos com uma dada classe, usaria a função de mapeamento:
// Arrow function (ES2015): var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName); // Standard function (since `Array.from` can be shimmed): var divs = Array.from(document.querySelectorAll(".some-class"), function(element) { return element.tagName; });
Se você usar as funções Array.prototype
com host-provided array-like objects (DOM lists and other things provided by the browser rather than the JavaScript engine), você precisa ter a certeza de testar nos seus ambientes de destino para se certificar de que o objecto fornecido pela máquina se comporta correctamente. A maioria comporta-se bem, mas é importante testar. A razão é que a maioria dos métodos Array.prototype
que você provavelmente quer usar dependem do objeto fornecido pelo host dando um resposta honesta ao resumo [[HasProperty]]
operação. A partir desta escrita, navegadores fazem um trabalho muito bom nisso, mas a spec 5.1 permitiu a possibilidade de um objeto hospedeiro fornecido pode não ser honesto. Está dentro §8.6.2, vários parágrafos abaixo da grande tabela perto do início dessa seção), onde diz:
Não encontrei a verbia equivalente na especificação ES2015, mas ainda deve ser o caso.) Mais uma vez, a partir desta escrita os objetos comuns array-provided array-like em navegadores modernos [Os objectos hospedeiros podem implementar estes métodos internos de qualquer forma, salvo indicação em contrário; por exemplo, uma possibilidade é que
[[Get]]
e[[Put]]
para um objecto de máquina em particular, obtém e armazena os valores da propriedade, mas[[HasProperty]]
gera sempre falso .
NodeList
instâncias, por exemplo] do lidar [[HasProperty]]
} corretamente, mas é importante testar.)
Edit : esta resposta está irremediavelmente desactualizada. Para uma abordagem mais moderna, olhe para Os métodos disponíveis em um array . Os métodos de interesse podem ser:
- forEach
- mapa
- filtro
- zip
- reduzir
- cada
- alguns
A forma padrão de iterar um array em JavaScript é uma baunilha for
- loop:
var length = arr.length,
element = null;
for (var i = 0; i < length; i++) {
element = arr[i];
// Do something with element
}
Note, No entanto, que esta abordagem só é boa se ter uma matriz densa, e cada índice é ocupado por um elemento. Se a matriz é escassa, então você pode encontrar problemas de desempenho com esta abordagem, uma vez que você vai iterar sobre um monte de índices que não realmente existem na matriz. Neste caso, um laço pode ser uma ideia melhor. No entanto , você deve usar as salvaguardas apropriadas para garantir que apenas as propriedades desejadas do array (ou seja, os elementos array) são aceitos, uma vez que o for..in
-loop também será enumerado nos navegadores antigos, ou se as propriedades adicionais forem definidas como enumerable
.
Em ECMAScript 5 {[10] } haverá um método forEach no protótipo do array, mas não é suportado nos navegadores legados. Então para ser capaz de usá-lo consistentemente você deve ter um ambiente que o suporta (por exemplo, nó .js for server side JavaScript), or use a "Polyfill". O Polifill para esta funcionalidade é, no entanto, trivial e uma vez que torna o código mais fácil de ler, é um bom polifill para incluir.
Se estiver a utilizar o jQuery biblioteca, você pode usar jQuery.cada:
$.each(yourArray, function(index, value) {
// do your stuff here
});
Editar :
Por pergunta, O Utilizador quer o código em javascript em vez de jQuery, por isso a edição é
var length = yourArray.length;
for (var i = 0; i < length; i++) {
// Do something with yourArray[i].
}
Volta para trás
Acho que o reverso do laço merece uma menção aqui:for (var i = array.length; i--; ) {
// process array[i]
}
Vantagens:
- não é necessário declarar uma variável temporária
len
, nem comparar comarray.length
em cada iteração, uma das quais poderá ser uma optimização de minutos. - remover irmãos do DOM em ordem inversa é normalmente mais eficiente. (O navegador precisa fazer menos deslocamento de elementos em seu interior matriz.)
- Se modificar a matriz while loop, durante ou após a index i (por exemplo, remover ou inserir um item em
array[i]
), então um ciclo para a frente iria ignorar o item que deslocado para a esquerda para a posição i, ou re-process ith item que foi deslocado para a direita. Em um tradicional laço, você poderia atualizar I para apontar para o próximo item que precisa de processamento-1, mas simplesmente reverter a direção da iteração é muitas vezes um solução mais simples e solução mais elegante. - da mesma forma, ao modificar ou remover os elementos DOM aninhados, o processamento em reverso pode contornar erros. Por exemplo, considere modificar o innerHTML de um nó pai antes de lidar com seus filhos. No momento em que o nó-criança é alcançado, ele será separado do DOM, tendo sido substituído por uma criança recém-criada quando o innerHTML do pai foi escrito.
- é mais curto para digitar, e leia , do que algumas das outras opções disponíveis. Apesar de perder para
forEach()
e para os ES6's.
Desvantagens:
- processa os itens em ordem inversa. Se você estava construindo uma nova matriz a partir dos resultados, ou imprimindo coisas na tela, naturalmente a saída será revertida em relação à ordem original.
- inserir repetidamente irmãos no DOM como um primeiro filho, a fim de manter a sua ordem é menos eficiente. (O navegador teria que mudar as coisas corretamente.) Para criar nós DOM de forma eficiente e em ordem, basta fazer um loop para a frente e adicionar como normal (e também usar um "fragmento de Documento").
- o ciclo inverso é confuso para os programadores Júnior. (Você pode considerar que uma vantagem, dependendo de sua perspectiva.)
Devo usá-lo sempre?
Alguns programadores usam o inverso para o loop por omissão , a menos que haja uma boa razão para seguir em frente.
Embora os ganhos de desempenho sejam normalmente insignificantes, parece que grita:"Faz isto a todos os itens da lista, não quero saber da ordem!"
No Entanto, na prática, que é não, na verdade, uma indicação confiável de intenções, uma vez que ele é indistinguível de uma dessas ocasiões, quando você fazer cuidados sobre a ordem, e realmente fazer necessidade para loop no sentido inverso. Por isso, na verdade ... outra construção seria necessária para expressar com precisão a intenção de "don't care", algo atualmente indisponível na maioria das línguas, incluindo ECMAScript, mas que poderia ser chamado, por exemplo, forEachUnordered()
.
Se a ordem não importa, e a eficiência é uma preocupação (no laço mais interior de um jogo ou motor de animação), então pode ser aceitável usar o inverso para o laço como o seu padrão go-to. Basta lembrar que ver um reverso para o loop no código existente Não necessariamente significa que a ordem é irrelevante!
É melhor usar forEach ()
Em geral, para um código de nível superior onde clareza e segurança são preocupações maiores, eu recomendaria usar Array::forEach
como o seu padrão por omissão:
- É claro ler.
- indica que I não vai ser deslocado dentro do bloco (o que é sempre uma possível surpresa escondida em longas
for
ewhile
loops.)
Dá você é uma escopo livre para fechamentos.
Reduz a fuga de variáveis locais e a colisão acidental com (e mutação) variáveis externas.
Então quando você vê o reverso para o loop em seu código, isso é uma dica de que ele é revertido por uma boa razão (talvez uma das razões descritas acima). E ver um avanço tradicional para o loop pode indicar que a mudança pode acontecer.
(Se a discussão de intenções não faz sentido para ti, Então tu e o teu código podem beneficie de assistir à palestra de Crockford sobre o estilo de programação e o seu cérebro.)
Como funciona?
for (var i = 0; i < array.length; i++) { ... } // Forwards
for (var i = array.length; i--; ) { ... } // Reverse
Você vai notar que i--
é a cláusula do meio (onde geralmente vemos uma comparação) e a última cláusula está vazia (onde normalmente vemos i++
). Isso significa que i--
também é usado como condiçãopara continuação. Crucialmente, é executado e verificado antes de cada iteração.
-
Como pode? começar em
array.length
sem explodir?Porque
i--
executa antes de cada iteração, na primeira iteração, nós vamos estar acessando o item emarray.length - 1
o que evita quaisquer questões comMatriz-out-of-boundsundefined
itens. -
Porque não pára de iterar antes do índice 0?
O laço vai parar de iterar quando a condição
O truque é que ao contrárioi--
se avalia a um valor de falsey (quando produz 0).--i
, os decrementos do operadori--
mas produz o valor antes o Decreto. A sua consola pode demonstrar isto:> var i = 5; [i, i--, i];
Assim, na última iteração, I foi anteriormente 1 e a expressão muda-a para 0 mas na verdade rende 1 (e assim a condição passa. Na próxima iteração[5, 5, 4]
i--
as alterações I a -1 mas rende 0 (falsey), fazendo com que a execução caia imediatamente do fundo do laço. ([34]} nos atacantes tradicionais para o laço,i++
e++i
são intercambiáveis (como Douglas Crockford aponta). No entanto, no reverso para o loop, porque o nosso decrement é também a nossa expressão de condição, nós devemos ficar comi--
Se queremos processar o item no índice 0.
Trivialidade
Algumas pessoas gostam de desenhar uma pequena seta no reverso., e termina com um piscar de olhos.for (var i = array.length; i --> 0 ;) {
os créditos vão para WYL por me mostrar os benefícios e horrores do reverso do loop.
Algumas linguagens do estilo usamforeach
para fazer loop através de enumerações. Em JavaScript isto é feito com o for..in
estrutura do ciclo:
var index,
value;
for (index in obj) {
value = obj[index];
}
Há um senão. for..in
irá percorrer cada um dos membros enumeráveis do objecto, e os membros no seu protótipo. Para evitar ler valores que são herdados através do protótipo do objeto, basta verificar se a propriedade pertence ao objeto:
for (i in obj) {
if (obj.hasOwnProperty(i)) {
//do stuff
}
}
Adicionalmente, ECMAScript 5 {[14] } adicionou um forEach
método para Array.prototype
que pode ser usado para enumerar sobre uma matriz usando um recuo (o polifill está nos documentos, de modo que você ainda pode usá-lo para navegadores mais antigos):
arr.forEach(function (val, index, theArray) {
//do stuff
});
É importante notar que Array.prototype.forEach
não se quebra quando o callback retorna false
. jQuery e sublinhado.js fornecem as suas próprias variações em each
para fornecer laços que podem ser de curto-circuito.
Se quiser fazer um loop sobre uma matriz, use o loop normal de três partes for
.
for (var i = 0; i < myArray.length; i++) {
var arrayItem = myArray[i];
}
Pode-se obter algumas optimizações de desempenho Cache myArray.length
ou iterando-se ao contrário.
A forEach implementation (see in jsFiddle):
function forEach(list,callback) {
var length = list.length;
for (var n = 0; n < length; n++) {
callback.call(list[n]);
}
}
var myArray = ['hello','world'];
forEach(
myArray,
function(){
alert(this); // do something
}
);
Se não se importar de esvaziar a matriz:
var x;
while(x = y.pop()){
alert(x); //do something
}
x
irá conter o último valor de y
e será removido do array. Você também pode usar shift()
que dará e removerá o primeiro item de y
.
Eu sei que este é um post antigo, e já há tantas grandes respostas. Para um pouco mais de Completude, pensei em juntar outro usando AngularJS. Claro, isso só se aplica se você estiver usando Angular, obviamente, no entanto, eu gostaria de colocá-lo de qualquer maneira.
angular.forEach
leva 2 argumentos e um terceiro argumento opcional. O primeiro argumento é o objeto (array) para iterar, o segundo argumento é a função iterator, e o terceiro argumento opcional é o contexto do objeto (basicamente referido dentro do laço como 'isto'.
Existem diferentes maneiras de usar o laço forEach do angular. O mais simples e provavelmente mais usado é
var temp = [1, 2, 3];
angular.forEach(temp, function(item) {
//item will be each element in the array
//do something
});
Outra maneira que é útil para copiar itens de uma matriz para outra é
var temp = [1, 2, 3];
var temp2 = [];
angular.forEach(temp, function(item) {
this.push(item); //"this" refers to the array passed into the optional third parameter so, in this case, temp2.
}, temp2);
No entanto, você não tem que fazer isso, você pode simplesmente fazer o seguinte e é equivalente ao exemplo anterior:
angular.forEach(temp, function(item) {
temp2.push(item);
});
Agora há prós e contras de usar a função angular.forEach
em oposição ao construído com sabor a baunilha.
Prós
- facilidade de leitura
- facilidade de contração
- Se disponível, {[4] } usará o circuito ES5 forEach. Agora, eu vou chegar a eficiência na seção cons, como os loops forEach são muito mais lentos do que os loops for. Menciono isto como profissional porque é bom ser consistente e padronizado.
Considere os seguintes 2 laços aninhados, que fazem exatamente a mesma coisa. Digamos que que temos 2 matrizes de objetos e cada objeto contém uma matriz de resultados, cada um dos quais tem uma propriedade de valor que é uma string (ou seja o que for). E digamos que precisamos de iterar cada um dos resultados e, se forem iguais, então executem alguma acção.
angular.forEach(obj1.results, function(result1) {
angular.forEach(obj2.results, function(result2) {
if (result1.Value === result2.Value) {
//do something
}
});
});
//exact same with a for loop
for (var i = 0; i < obj1.results.length; i++) {
for (var j = 0; j < obj2.results.length; j++) {
if (obj1.results[i].Value === obj2.results[j].Value) {
//do something
}
}
}
Admito que este é um exemplo hipotético muito simples, mas eu escrevi o triplo embutido para loops usando a segunda abordagem e foi Muito difícil de ler, e escrever para isso questao.
Cons
- Eficiência.
angular.forEach
, e o nativo forEach
, por falar nisso, são ambos Muito mais lentos do que o laço normal for
....cerca de 90% mais lento . Assim, para grandes conjuntos de dados, o melhor é manter o laço nativo for
.
Sem Pausa, Continuar ou devolver o suporte. continue
é realmente suportado por " acidente ", para continuar em um {[[4] } Você simples colocar uma declaração return;
na função como angular.forEach(array, function(item) { if (someConditionIsTrue) return; });
o que fará com que a continue fora da função para essa iteração. Isto também se deve ao fato de que o nativo forEach
não suporta quebrar ou continuar.
Uma solução fácil agora seria usar o sublinhado de .js library. Ele está fornecendo muitas ferramentas úteis, como each
e irá automaticamente delegar o trabalho para o nativo forEach
se disponível.
Um exemplo do CodePen de como funciona é:
var arr = ["elemA", "elemB", "elemC"];
_.each(arr, function(elem, index, ar)
{
...
});
Ver também
-
documentação para os nativos
Array.prototype.forEach()
. - em for_each...in (MDN) explica-se que
for each (variable in object)
está desactualizado como parte do ECMA-357. (EAX) padrão. -
para...de (MDN) descreve a próxima forma de iterar usando
for (variable of object)
como parte da proposta Harmony (ECMAScript 6).
Provavelmente o laço for(i = 0; i < array.length; i++)
não é a melhor escolha. Por quê? Se tiver isto:
var array = new Array();
array[1] = "Hello";
array[7] = "World";
array[11] = "!";
O método vai ligar de array[0]
para array[2]
. Primeiro, isso irá primeiro variáveis de referência que você nem tem, segundo você não teria as variáveis na matriz, e terceiro isso vai tornar o código mais ousado. Olha, é o que eu uso.
for(var i in array){
var el = array[i];
//If you want 'i' to be INT just put parseInt(i)
//Do something with el
}
E se queres que seja uma função, podes fazer isto:
function foreach(array, call){
for(var i in array){
call(array[i]);
}
}
Se quiseres partir, um pouco mais lógica:
function foreach(array, call){
for(var i in array){
if(call(array[i]) == false){
break;
}
}
}
Exemplo:
foreach(array, function(el){
if(el != "!"){
console.log(el);
} else {
console.log(el+"!!");
}
});
Devolve:
//Hello
//World
//!!!
Existem três implementações de foreach
em jQuery como se segue.
var a = [3,2];
$(a).each(function(){console.log(this.valueOf())}); //Method 1
$.each(a, function(){console.log(this.valueOf())}); //Method 2
$.each($(a), function(){console.log(this.valueOf())}); //Method 3
A partir do ES6:
list = [0, 1, 2, 3]
for (let obj of list) {
console.log(obj)
}
Onde of
evita as esquisitices associadas a in
e faz com que funcione como o laço for
de qualquer outra linguagem, e let
liga-se i
dentro do laço em oposição a dentro da função.
Os suspensórios ({}
) podem ser omitidos quando existe apenas um comando (por exemplo, no exemplo acima).
Não há nenhum laço for each
em nativoJavaScript . Você pode usar bibliotecas para obter esta funcionalidade (eu recomendo sublinhado.js ), use um simples for
em laço.
for (var instance in objects) {
...
}
No entanto, note que pode haver razões para usar um loop ainda mais simples for
(ver a questão de fluxo de pilha por que está usando "for...in" com a iteração da matriz é assim tão má ideia?)
var instance;
for (var i=0; i < objects.length; i++) {
var instance = objects[i];
...
}
Este é um iterador para uma lista não-esparsa onde o índice começa em 0, que é o cenário típico ao lidar com o documento.getElementsByTagName ou document.querySelectorAll)
function each( fn, data ) {
if(typeof fn == 'string')
eval('fn = function(data, i){' + fn + '}');
for(var i=0, L=this.length; i < L; i++)
fn.call( this[i], data, i );
return this;
}
Array.prototype.each = each;
Exemplos de Utilização:
Exemplo #1
var arr = [];
[1, 2, 3].each( function(a){ a.push( this * this}, arr);
arr = [1, 4, 9]
Exemplo #2
each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');
Cada etiqueta p recebe class="blue"
Exemplo #3
each.call(document.getElementsByTagName('p'),
"if( i % 2 == 0) this.className = data;",
'red'
);
Todas as outras etiquetas p recebem class="red"
>
Exemplo #4
each.call(document.querySelectorAll('p.blue'),
function(newClass, i) {
if( i < 20 )
this.className = newClass;
}, 'green'
);
E finalmente ... as primeiras 20 etiquetas p azuis são alteradas para verde
Cuidado ao usar string como função: a função é criada fora de contexto e deve ser usada apenas onde você tem certeza de escopo variável. Caso contrário, é melhor passar funções onde escopo é mais intuitivo.
Existem algumas maneiras de percorrer um array em JavaScript, como abaixo:
- é a mais comum. Bloco completo de código para looping
var languages = ["JAVA", "JavaScript", "C#", "Python"];
var i, len, text;
for (i = 0, len = languages.length, text = ""; i < len; i++) {
text += languages[i] + "<br>";
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>
Enquanto - loop enquanto uma condição está terminada. Parece ser o loop mais rápido
var text = "";
var i = 0;
while (i < 10) {
text += i + ") something<br>";
i++;
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>
Do / while - também loop através de um bloco de código, enquanto o a condição é verdadeira, vai correr pelo menos uma vez
var text = ""
var i = 0;
do {
text += i + ") something <br>";
i++;
}
while (i < 10);
document.getElementById("example").innerHTML = text;
<p id="example"></p>
Laços funcionais - forEach
, map
, filter
, também reduce
(Eles fazem loop através da função, mas usado se você precisa fazer algo com o seu array, etc.
// For example, in this case we loop through the number and double them up using the map function
var numbers = [65, 44, 12, 4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num * 2});
<p id="example"></p>
Array#some
como em baixo:
[1,2,3].some(function(number) {
return number === 1;
});
Isto funciona porque some
devolve verdadeiro assim que qualquer um dos callbacks, executado por ordem de matriz, devolve verdadeiro, fazendo curto-circuito na execução do resto.
Resposta Original
ver Array prototype for some
ECMAScript5 (a versão em Javascript) para trabalhar com Arrays.
ForEach - itera através de cada item da matriz e faz o que for preciso com cada item.
['C', 'D', 'E'].forEach(function(element, index) {
console.log(element + " is the #" + (index+1) + " in musical scale");
});
// Output
// C is the #1 in musical scale
// D is the #2 in musical scale
// E is the #3 in musical scale
No caso de, estar mais interessado na operação em array usando alguma funcionalidade incorporada.
Map - cria um novo array com o resultado da função de callback. Este método é bom para ser usado quando você precisa formatar os elementos de seu array.
// Let's upper case the items in the array
['bob', 'joe', 'jen'].map(function(elem) {
return elem.toUpperCase();
});
// Output: ['BOB', 'JOE', 'JEN']
Reduzir o nome diz que reduz o array a um único valor, chamando a função dada passando no elemento currentct e o resultado da execução anterior.
[1,2,3,4].reduce(function(previous, current) {
return previous + current;
});
// Output: 10
// 1st iteration: previous=1, current=2 => result=3
// 2nd iteration: previous=3, current=3 => result=6
// 3rd iteration: previous=6, current=4 => result=10
Cada - Devolve verdadeiro ou falso se todos os elementos da matriz passarem no teste na função de callback.
// Check if everybody has 18 years old of more.
var ages = [30, 43, 18, 5];
ages.every(function(elem) {
return elem >= 18;
});
// Output: false
Filtro - muito semelhante a todos, excepto que o filtro devolve um array com os elementos que retornam verdadeiros à função indicada.
// Finding the even numbers
[1,2,3,4,5,6].filter(function(elem){
return (elem % 2 == 0)
});
// Output: [2,4,6]
Espero que isto seja útil.
var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
console.log(item);
}
Prós:
{[[2]} o benefício para isto: você já tem a referência no primeiro como isso não precisa ser declarado mais tarde com outra linha. É útil quando se faz looping através do conjunto de objetos.Cons:
Isto irá quebrar sempre que a referência for falsa - falsey (indefinida, etc.). Pode ser utilizado como mas é uma vantagem. No entanto, seria um pouco mais difícil de ler. E também dependendo do navegador pode ser" não " otimizado para trabalhar mais rápido do que o original.
JQuery way using $.map
:
var data = [1, 2, 3, 4, 5, 6, 7];
var newData = $.map(data, function(element) {
if (element % 2 == 0) {
return element;
}
});
// newData = [2, 4, 6];
Uma maneira mais próxima da sua ideia seria usar {[[2]} que aceita uma função de clojure que será executada para cada elemento da matriz.
myArray.forEach(
(item) => {
// do something
console.log(item);
}
);
Outra forma viável seria usar {[3] } que funciona da mesma forma, mas também mutates
cada elemento e devolve-o como:
var myArray = [1, 2, 3];
myArray = myArray.map(
(item) => {
return item + 1;
}
);
console.log(myArray); // [2, 3, 4]
A sintaxe lambda normalmente não funciona em IE 10 ou em baixo.
Normalmente uso o
[].forEach.call(arrayName,function(value,index){
console.log("value of the looped element" + value);
console.log("index of the looped element" + index);
});
If you are a jQuery Fan and already have a jQuery file running, you should reverse the positions of the index and value parameters
$("#ul>li").each(function(**index,value**){
console.log("value of the looped element" + value);
console.log("index of the looped element" + index);
});
var a = ["car", "bus", "truck"]
a.forEach(function(item, index) {
console.log("Index" + index);
console.log("Element" + item);
})
let Array = [1,3,2];
theArray.forEach((element)=>{
// use the element of the array
console.log(element)
}
O elemento terá o valor de cada índice de 0 ao comprimento da matriz.
Resultado:
1
3
2
Explicação:
O ForEach está na classe protótipo. você também pode chamar isso de theArray.prototipo.forEach(...);
Protótipo: https://hackernoon.com/prototypes-in-javascript-5bba2990e04b
Você também pode alterar sobre uma matriz como esta:
for(let i=0;i<theArray.length;i++){
console.log(i); //i will have the value of each index
}
Se quiser usar forEach()
, vai parecer - se com -
theArray.forEach ( element => {
console.log(element);
});
Se quiser usar for()
, vai parecer -
for(let idx = 0; idx < theArray.length; idx++){
let element = theArray[idx];
console.log(element);
}
Se tem uma grande variedade deve usar iterators
para ganhar alguma eficiência. Iteradores são uma propriedade de certos JavaScript coleções (como Map
, Set
, String
, Array
). Mesmo, for..of
utilizações iterator
debaixo do capô.
value
da rubrica actual e de a boolean
indicar quando chegou ao fim da colecção. O seguinte é um exemplo de criação de um iterador de matriz.
Transforme a sua matriz regular em iterador usando values()
método como este:
const myArr = [2,3,4]
let it = myArr.values();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
Você também pode transformar o seu array regular para iterador usando Symbol.iterator
assim:
const myArr = [2,3,4]
let it = myArr[Symbol.iterator]();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
Também pode transformar o seu Normal {[15] } num iterator
Assim.:
let myArr = [8, 10, 12];
function makeIterator(array) {
var nextIndex = 0;
return {
next: function() {
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true};
}
};
};
var it = makeIterator(myArr);
console.log(it.next().value); // {value: 8, done: false}
console.log(it.next().value); // {value: 10, done: false}
console.log(it.next().value); // {value: 12, done: false}
console.log(it.next().value); // {value: undefined, done: true}
Nota:
- Os iteradores são de natureza exaustiva.
- os objectos não são
iterable
por omissão. Utilizaçãofor..in
nesse caso, porque em vez de valores funciona com chaves.
iteration protocol
toma.
Resumo:
[[40]] quando iterando sobre uma matriz, muitas vezes podemos querer alcançar um dos seguintes objetivos:-
Queremos entrar no array e criar um novo array.
Array.prototype.map
-
Queremos entrar no array e não criar um novo array.
Array.prototype.forEach
for..of
ciclo
A criar uma nova matriz: Map
map()
é uma função localizada em Array.prototype
que pode transformar todos os elementos de um array e depois devolve um array novo. map()
toma como argumento uma função de callback e funciona da seguinte maneira:
let arr = [1, 2, 3, 4, 5];
let newArr = arr.map((element, index, array) => {
return element * 2;
})
console.log(arr);
console.log(newArr);
map()
como um argumento é executado para cada elemento. Em seguida, um array é devolvido que tem o mesmo comprimento que o array original. Neste novo elemento array é transformado pela função callback passada como um argumento para map()
.
A diferença distinta entre map
e outros loop mecanismo como forEach
e for..of
loop que são map
retorna como nova matriz e deixa a velha matriz intacta (exceto se explicitamente manipulá-lo com o pensa como splice
).
Note também que o callback da função map
fornece como segundo argumento o número de índice da iteração actual. Além disso, o terceiro argumento fornece a matriz na qual map
foi chamado. Às vezes estas propriedades podem ser muito úteis.
Circuito com forEach
forEach
é uma função que está localizada em Array.prototype
que toma uma função de callback como um argumento. Ele então executa esta função de callback para cada elemento na matriz. Em contraste com o map()
função a função forEach não devolve nada (undefined
). Por exemplo:
let arr = [1, 2, 3, 4, 5];
arr.forEach((element, index, array) => {
console.log(element * 2);
if (index === 4) {
console.log(array)
}
// index, and oldArray are provided as 2nd and 3th argument by the callback
})
console.log(arr);
Assim como a função map
, o callback forEach
fornece como segundo argumento o número de índice da iteração actual. Também o terceiro argumento fornece a matriz na qual forEach
foi chamado.
Circular através de elementos usando for..of
O laço for..of
passa por todos os elementos de uma matriz (ou qualquer outro objecto iterável). Funciona em a seguinte maneira:
let arr = [1, 2, 3, 4, 5];
for(let element of arr) {
console.log(element * 2);
}
No exemplo acima element
representa um elemento array e arr
é o array que queremos fazer circular. Não que o nome element
seja arbitrário e poderíamos ter escolhido qualquer outro nome como 'el' ou algo mais declarativo quando isso for aplicável.
for..in
fará um loop através de todas as propriedades enumeráveis do array, enquanto que o loop for..of
fará apenas um loop. circular pelos elementos do array. Por exemplo:
let arr = [1, 2, 3, 4, 5];
arr.foo = 'foo';
for(let element of arr) {
console.log(element);
}
for(let element in arr) {
console.log(element);
}
function printList(callback) {
// do your printList work
console.log('printList is done');
callback();
}
function updateDB(callback) {
// do your updateDB work
console.log('updateDB is done');
callback()
}
function getDistanceWithLatLong(callback) {
// do your getDistanceWithLatLong work
console.log('getDistanceWithLatLong is done');
callback();
}
function runSearchInOrder(callback) {
getDistanceWithLatLong(function() {
updateDB(function() {
printList(callback);
});
});
}
runSearchInOrder(function(){console.log('finished')});
A saída é igual à saída a festa com a Lothian acabou. o updateDB está pronto a lista de impressões está pronta terminado