Qual é a diferença entre (para… in) e (para… de) em javascript?

Eu sei o que é for... in loop (iterar sobre chave), mas ouvi pela primeira vez sobre for... of (iterar sobre o valor). Estou confuso com for... of loop. Eu não recebi o adjetivo. Este é o código abaixo:

 var arr = [3, 5, 7]; arr.foo = "hello"; for (var i in arr) { console.log(i); // logs "0", "1", "2", "foo" } for (var i of arr) { console.log(i); // logs "3", "5", "7" //it is does not log "3", "5", "7","hello" } 

O que eu tenho é, for... of iterações sobre valores de propriedade. então por que ele não registra (retorna) "3", "5", "7","hello" vez de "3", "5", "7" ? mas for... in loop iterar sobre cada tecla (“0”, “1”, “2”, “foo”). aqui for... in loop também iterar sobre foo key. mas para … de não iterarte sobre o valor da propriedade foo ou seja, "hello" .Por que é assim?

Longa história em resumo:

aqui eu consolo for... of loop. deve ser log "3", "5", "7","hello" mas aqui ele registra "3", "5", "7" . Por quê ?

Link de exemplo

for in loops for in sobre nomes de propriedades enumeráveis ​​de um object.

for of (novo no ES6) usa um iterador específico do object e faz um loop sobre os valores gerados por ele.

No seu exemplo, o iterador da matriz produz todos os valores na matriz (ignorando as propriedades que não são de índice).

Eu encontrei uma resposta completa em: https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html (Embora seja para o tipo script, isso é o mesmo para o javascript também)

Ambas as for..of and for..in for..of sobre listas; entretanto, os valores iterados são diferentes, for..in retorna uma lista de chaves no object que está sendo iterado, enquanto for..of retorna uma lista de valores das propriedades numéricas do object que está sendo iterado.

Aqui está um exemplo que demonstra essa distinção:

 let list = [4, 5, 6]; for (let i in list) { console.log(i); // "0", "1", "2", } for (let i of list) { console.log(i); // "4", "5", "6" } 

Outra distinção é que for..in opera em qualquer object; serve como uma maneira de inspecionar propriedades neste object. for..of por outro lado, está principalmente interessado em valores de objects iteráveis. Objetos internos como Map e Set implement Symbol.iterator propriedade implement Symbol.iterator , permitindo o access aos valores armazenados.

 let pets = new Set(["Cat", "Dog", "Hamster"]); pets["species"] = "mammals"; for (let pet in pets) { console.log(pet); // "species" } for (let pet of pets) { console.log(pet); // "Cat", "Dog", "Hamster" } 

Para … em loop

O loop for … in aumenta as fraquezas do loop for, eliminando a lógica de contagem e a condição de saída.

Exemplo:

 const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (const index in digits) { console.log(digits[index]); } 

Mas, você ainda tem que lidar com o problema de usar um índice para acessar os valores da matriz, e isso fede; isso quase torna mais confuso do que antes.

Além disso, o loop for … in pode causar grandes problemas quando você precisar adicionar um método extra a uma matriz (ou outro object). Porque for loops em loop em todas as propriedades enumeráveis, isso significa que se você adicionar propriedades adicionais ao protótipo da matriz, essas propriedades também aparecerão no loop.

 Array.prototype.decimalfy = function() { for (let i = 0; i < this.length; i++) { this[i] = this[i].toFixed(2); } }; const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (const index in digits) { console.log(digits[index]); } 

Impressões:

0

1

2

3

4

5

6

7

8

9

function () {para (let i = 0; i

É por isso que para ... os loops são desencorajados ao executar o loop por matrizes.

NOTA : O loop forEach é outro tipo de loop para JavaScript. No entanto, forEach() é na verdade um método de matriz, portanto, ele pode ser usado exclusivamente com matrizes. Também não há como interromper ou interromper um loop forEach. Se você precisar desse tipo de comportamento no seu loop, você terá que usar um loop básico.

Para ... de loop

O loop for ... é usado para fazer loop em qualquer tipo de dado iterável.

Exemplo:

 const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (const digit of digits) { console.log(digit); } 

Impressões:

0

1

2

3

4

5

6

7

8

9

Isso faz com que o for ... do loop seja a versão mais concisa de todos os loops for.

Mas espere, tem mais! O loop for ... também tem alguns benefícios adicionais que corrigem as fraquezas dos loop for e for ... in.

Você pode parar ou interromper um loop de ... a qualquer momento.

 const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (const digit of digits) { if (digit % 2 === 0) { continue; } console.log(digit); } 

Impressões:

1

3

5

7

9

E você não precisa se preocupar em adicionar novas propriedades aos objects. O loop for ... of irá fazer um loop somente sobre os valores no object.

A instrução for-in itera sobre as propriedades enumeráveis ​​de um object, em ordem arbitrária.

O loop irá iterar sobre todas as propriedades enumeráveis ​​do próprio object e aquelas que o object herda do protótipo do construtor.

Você pode pensar nisso como “for in” basicamente itera e lista todas as chaves.

 var str = 'abc'; var arrForOf = []; var arrForIn = []; for(value of str){ arrForOf.push(value); } for(value in str){ arrForIn.push(value); } console.log(arrForOf); // ["a", "b", "c"] console.log(arrForIn); // ["0", "1", "2", "formatUnicorn", "truncate", "splitOnLast", "contains"] 

Existem alguns tipos de dados já definidos que nos permitem iterar sobre eles facilmente, por exemplo, Array, Map, String Objects

Normal por em itera sobre o iterador e em resposta nos fornece as chaves que estão na ordem de inserção, como mostrado no exemplo abaixo.

  const numbers = [1,2,3,4,5]; for(let number in number) { console.log(number); } // result: 0, 1, 2, 3, 4 

Agora, se tentamos o mesmo com for , então, em resposta, ele nos fornece os valores e não as chaves. por exemplo

  const numbers = [1,2,3,4,5]; for(let numbers of numbers) { console.log(number); } // result: 1, 2, 3, 4, 5 

Portanto, olhando para os dois iteradores, podemos facilmente diferenciar a diferença entre os dois.

Nota: – Somente para trabalhos com o Symbol.iterator

Então, se tentarmos iterar sobre objects normais, isso nos dará um erro, por exemplo.

 const Room = { area: 1000, height: 7, floor: 2 } for(let prop in Room) { console.log(prop); } // Result area, height, floor for(let prop of Room) { console.log(prop); } 

O quarto não é iterável

Agora, para repetir, precisamos definir um ES6 Symbol.iterator, por exemplo

  const Room= { area: 1000, height: 7, floor: 2, [Symbol.iterator]: function* (){ yield this.area; yield this.height; yield this.floors; } } for(let prop of Room) { console.log(prop); } //Result 1000, 7, 2 

Essa é a diferença entre For in e For of . Espero que isso possa limpar a diferença.

A instrução for … in itera sobre as propriedades enumeráveis ​​de um object, em uma ordem arbitrária. As propriedades enumeráveis ​​são aquelas cujo sinalizador [[Enumerable]] interno está definido como true, portanto, se houver alguma propriedade enumerável na cadeia de protótipos, o loop for … in iterará também sobre elas.

A instrução for … de itera sobre dados que o object iterável define para ser iterado.

Exemplo

 Object.prototype.objCustom = function() {}; Array.prototype.arrCustom = function() {}; let iterable = [3, 5, 7]; for (let i in iterable) { console.log(i); // logs 0, 1, 2, "arrCustom", "objCustom" } for (let i in iterable) { if (iterable.hasOwnProperty(i)) { console.log(i); // logs 0, 1, 2, } } for (let i of iterable) { console.log(i); // logs 3, 5, 7 } 

Como antes você pode pular adicionando “hasOwnProperty” em … de loops.

Todos explicaram por que esse problema ocorre, mas ainda é muito fácil esquecê-lo e, em seguida, coçar a cabeça por que você obteve resultados errados. Especialmente quando você está trabalhando em grandes conjuntos de dados, quando os resultados parecem estar bem à primeira vista.

Usando Object.entries você garante percorrer todas as propriedades:

 var arr = [3, 5, 7]; arr.foo = "hello"; for (var [key,val] of Object.entries(arr)) { console.log( val ); } //result //3 //5 //7 //hello