Generator comprehensions

Você está lendo a versão em inglês deste conteúdo porque ainda não há uma tradução para este idioma. Ajude-nos a traduzir este artigo!

Non-standard
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

Obsolete since Gecko 58 (Firefox 58 / Thunderbird 58 / SeaMonkey 2.55)
This feature is obsolete. Although it may still work in some browsers, its use is discouraged since it could be removed at any time. Try to avoid using it.

Não padronizado. Não use!
A sintaxe de generator comprehensions não é padronizada e foi removida a partir do Firefox 58. Para usos futuros, considere o uso de generator.

A sintaxe de generator comprehension foi uma expressão em JavaScript que permitia montar rapidamente um nova função geradora baseada em um objeto iterável existente. Porém, ela foi removida do padrão e da implementação Firefox. Não a use!

Sintaxe

(for (x of iterable) x)
(for (x of iterable) if (condition) x)
(for (x of iterable) for (y of iterable) x + y)

Descrição

Dentro de generator comprehensions, são permitidos dois tipos de componentes:

A iteração for-of é sempre o primeiro componente. Várias iterações for-of or declarações if são permitidas.

Uma desvantagem significativa das array comprehensions é que elas causam a construção de um array inteiro na memória. Quando a entrada para a comprehension é em si um pequeno array ,a sobrecarga envolvida é insignificante — mas quando a entrada é um grande array ou um generator custoso (ou mesmo infinito), a criação de um novo array pode ser problemática.

Geradores permitem o cálculo lento de sequências, com items calculados sob demanda conforme a necessidade. Generator comprehensions são sintaticamente quase idênticos aos array comprehensions — elas usam parênteses invés de chaves — mas invés de construir um array, criam um gerador que pode executar lentamente. Eles podem ser considerados como uma sintaxe abreviada para criar geradores

Suponha que temos um interador it que itera sobre uma grande sequência de inteiros. Queremos criar um novo iterador que irá iterar sobre seus dobros. Um array comprehension criaria na memória um array completo contendo os valores dobrados:

var doubles = [for (i in it) i * 2];

Um generator comprehension por outro lado criaria um novo iterador que criaria valores dobrados sob demanda conforme a necessidade:

var it2 = (for (i in it) i * 2);
console.log(it2.next()); // O primeiro valor, duplicado
console.log(it2.next()); // O segundo valor, duplicado

Quando um generator comprehension é usado como um argumento para uma função, os parênteses usados para a chamada da função significam que os parênteses externos podem ser omitidos:

var result = doSomething(for (i in it) i * 2);

A diferença significativa entre os dois exemplos começam pelo uso da generator comprehension, você teria apenas que fazer um loop sobre a estrutura 'obj' uma vez, total, ao invés de uma vez ao compreender o array, e mais uma vez ao iterar sobre ele.

Exemplos

Simples generator comprehensions

(for (i of [1, 2, 3]) i * i );
// generator function which yields 1, 4, and 9

[...(for (i of [1, 2, 3]) i * i )];
// [1, 4, 9]

var abc = ['A', 'B', 'C'];
(for (letters of abc) letters.toLowerCase());
// generator function which yields "a", "b", and "c"

Generator comprehensions com declaração if

var years = [1954, 1974, 1990, 2006, 2010, 2014];

(for (year of years) if (year > 2000) year);
// generator function which yields 2006, 2010, and 2014

(for (year of years) if (year > 2000) if (year < 2010) year);
// generator function which yields 2006, the same as below:

(for (year of years) if (year > 2000 && year < 2010) year);
// generator function which yields 2006

Generator comprehensions comparadas à função geradora

Um maneira fácil de entender a sintaxe de generator comprehension, é compará-la com a função geradora.

Exemplo 1: Gerador simples.

var numbers = [1, 2, 3];

// Generator function
(function*() {
  for (let i of numbers) {
    yield i * i;
  }
})();

// Generator comprehension
(for (i of numbers) i * i );

// Result: both return a generator which yields [1, 4, 9]

Exemplo 2: Usando if no gerador.

var numbers = [1, 2, 3];

// Generator function
(function*() {
  for (let i of numbers) {
    if (i < 3) {
      yield i * 1;
    }
  }
})();

// Generator comprehension
(for (i of numbers) if (i < 3) i);

// Result: both return a generator which yields [1, 2]

Especificações

As generator comprehensions estavam inicialmente no rascunho do ECMAScript 2015, mas foram removidas na revisão 27 (agosto de 2014). Por favor, veja as revisões mais antigas do ES2015 para a semântica de especificação.

Compatibilidade do navegador

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
Generator comprehensions
DeprecatedNon-standard
Chrome No support NoEdge No support NoFirefox No support 30 — 58IE No support NoOpera No support NoSafari No support NoWebView Android No support NoChrome Android No support NoFirefox Android No support 30 — 58Opera Android No support NoSafari iOS No support NoSamsung Internet Android No support Nonodejs No support No

Legend

No support  
No support
Non-standard. Expect poor cross-browser support.
Non-standard. Expect poor cross-browser support.
Deprecated. Not for use in new websites.
Deprecated. Not for use in new websites.

Diferenças para as antigas JS1.7/JS1.8 comprehensions

Comprehensions das versões JS1.7/JS1.8 foram removidas da Gecko 46 (bug 1220564).

Sintaxe antiga das comprehensions (não use mais!):

(X for (Y in Z))
(X for each (Y in Z))
(X for (Y of Z))

Diferenças:

  • Comprehensions na ES7 criam um escopo para cada nó "for" invés da comprehension como um todo.
    • Antiga: [...(()=>x for (x of [0, 1, 2]))][1]() // 2
    • Nova: [...(for (x of [0, 1, 2]) ()=>x)][1]() // 1, cada iteração cria uma nova ligação para x.
  • Comprehensions na ES7 começam com "for" invés da expressão de atribuição.
    • Antiga: (i * 2 for (i of numbers))
    • Nova: (for (i of numbers) i * 2)
  • Comprehensions na ES7 podem ter vários componentes if e for.
  • Comprehensions na ES7 apenas trabalham com for...of e não com iterações for...in.

Veja também