Questa pagina contiene un errore di script. Nell’attesa che venga corretto dagli editori del sito, è possibile visualizzare qui di seguito una versione provvisoria dei contenuti.

I volontari di MDN non hanno ancora tradotto questo articolo in Italiano. Unisciti a noi e traducilo tu stesso.
Puoi anche consultare l’articolo in English (US).

Non-standard. Do not use!
The array comprehensions syntax is non-standard and removed starting with Firefox 58. For future-facing usages, consider using {{jsxref("Array.prototype.map")}}, {{jsxref("Array.prototype.filter")}}, {{jsxref("Functions/Arrow_functions", "arrow functions", "", 1)}}, and {{jsxref("Operators/Spread_operator", "spread syntax", "", 1)}}.
{{jsSidebar("Operators")}}

The array comprehension syntax was a JavaScript expression which allowed you to quickly assemble a new array based on an existing one. However, it has been removed from the standard and the Firefox implementation. Do not use it!

Syntax

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

Description

Inside array comprehensions, these two kinds of components are allowed:

  • {{jsxref("Statements/for...of", "for...of")}} and
  • {{jsxref("Statements/if...else", "if")}}

The for-of iteration is always the first component. Multiple for-of iterations or if statements are allowed.

Array comprehension was previously proposed to be standardized in ECMAScript 2016, it provide a useful shortcut for constructing a new array based on the contents of another. Comprehensions can often be used in place of calls to {{jsxref("Array.prototype.map", "map()")}} and {{jsxref("Array.prototype.filter", "filter()")}}, or as a way of combining the two.

The following comprehension takes an array of numbers and creates a new array of the double of each of those numbers.

var numbers = [1, 2, 3, 4];
var doubled = [for (i of numbers) i * 2];
console.log(doubled); // logs 2,4,6,8

This is equivalent to the following {{jsxref("Array.prototype.map", "map()")}} operation:

var doubled = numbers.map(i => i * 2);

Comprehensions can also be used to select items that match a particular expression. Here is a comprehension which selects only even numbers:

var numbers = [1, 2, 3, 21, 22, 30];
var evens = [for (i of numbers) if (i % 2 === 0) i];
console.log(evens); // logs 2,22,30

{{jsxref("Array.prototype.filter", "filter()")}} can be used for the same purpose:

var evens = numbers.filter(i => i % 2 === 0);

{{jsxref("Array.prototype.map", "map()")}} and {{jsxref("Array.prototype.filter", "filter()")}} style operations can be combined into a single array comprehension. Here is one that filters just the even numbers, then creates an array containing their doubles:

var numbers = [1, 2, 3, 21, 22, 30];
var doubledEvens = [for (i of numbers) if (i % 2 === 0) i * 2];
console.log(doubledEvens); // logs 4,44,60

The square brackets of an array comprehension introduce an implicit block for scoping purposes. New variables (such as i in the example) are treated as if they had been declared using {{jsxref("Statements/let","let")}}. This means that they will not be available outside of the comprehension.

The input to an array comprehension does not itself need to be an array; iterators and generators can also be used.

Even strings may be used as input; to achieve the filter and map actions (under Array-like objects) above:

var str = 'abcdef';
var consonantsOnlyStr = [for (c of str) if (!(/[aeiouAEIOU]/).test(c)) c].join(''); // 'bcdf'
var interpolatedZeros = [for (c of str) c + '0' ].join(''); // 'a0b0c0d0e0f0'

Again, the input form is not preserved, so we have to use {{jsxref("Array.prototype.join", "join()")}} to revert back to a string.

Examples

Simple array comprehensions

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

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

Array comprehensions with if statement

var years = [1954, 1974, 1990, 2006, 2010, 2014];
[for (year of years) if (year > 2000) year];
// [2006, 2010, 2014]
[for (year of years) if (year > 2000) if (year < 2010) year];
// [2006], the same as below:
[for (year of years) if (year > 2000 && year < 2010) year];
// [2006] 

Array comprehensions compared to map and filter

An easy way to understand array comprehension syntax, is to compare it with the Array {{jsxref("Array.map", "map")}} and {{jsxref("Array.filter", "filter")}} methods:

var numbers = [1, 2, 3];

numbers.map(function (i) { return i * i });
numbers.map(i => i * i);
[for (i of numbers) i * i];
// all are [1, 4, 9]

numbers.filter(function (i) { return i < 3 });
numbers.filter(i => i < 3);
[for (i of numbers) if (i < 3) i];
// all are [1, 2]

Array comprehensions with two arrays

Using two for-of iterations to work with two arrays:

var numbers = [1, 2, 3];
var letters = ['a', 'b', 'c'];

var cross = [for (i of numbers) for (j of letters) i + j];
// ["1a", "1b", "1c", "2a", "2b", "2c", "3a", "3b", "3c"]

var grid = [for (i of numbers) [for (j of letters) i + j]];
// [
//  ["1a", "1b", "1c"],
//  ["2a", "2b", "2c"],
//  ["3a", "3b", "3c"]
// ]

[for (i of numbers) if (i > 1) for (j of letters) if(j > 'a') i + j]
// ["2b", "2c", "3b", "3c"], the same as below:

[for (i of numbers) for (j of letters) if (i > 1) if(j > 'a') i + j]
// ["2b", "2c", "3b", "3c"]

[for (i of numbers) if (i > 1) [for (j of letters) if(j > 'a') i + j]]
// [["2b", "2c"], ["3b", "3c"]], not the same as below:

[for (i of numbers) [for (j of letters) if (i > 1) if(j > 'a') i + j]]
// [[], ["2b", "2c"], ["3b", "3c"]]

Specifications

Was initially in the ECMAScript 2015 draft, but got removed in revision 27 (August 2014). Please see older revisions of ES2015 for specification semantics.

Browser compatibility

{{Compat("javascript.operators.array_comprehensions")}}

Differences to the older JS1.7/JS1.8 comprehensions

JS1.7/JS1.8 comprehensions are removed from Gecko starting with version 46 ({{bug(1220564)}}).

Old comprehensions syntax (do not use anymore!):

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

Differences:

  • ESNext comprehensions create one scope per "for" node instead of the comprehension as a whole.
    • Old: [()=>x for (x of [0, 1, 2])][1]() // 2
    • New: [for (x of [0, 1, 2]) ()=>x][1]() // 1, each iteration creates a fresh binding for x.
  • ESNext comprehensions start with "for" instead of the assignment expression.
    • Old: [i * 2 for (i of numbers)]
    • New: [for (i of numbers) i * 2]
  • ESNext comprehensions can have multiple if and for components.
  • ESNext comprehensions only work with {{jsxref("Statements/for...of", "for...of")}} and not with {{jsxref("Statements/for...in", "for...in")}} iterations.

See Bug 1220564, comment 42 for suggestions on updating code.

See also

  • {{jsxref("Statements/for...of", "for...of")}}
  • {{jsxref("Operators/Generator_comprehensions", "Generator comprehensions", "" ,1)}}

Tag del documento e collaboratori

Hanno collaborato alla realizzazione di questa pagina: fscholz, shoelaces, nmve, spicyj, kdex, isonic, tschneidereit, arai, TimothyGu, so_matt_basta, jwhitlock, P0lip, cirocosta, ziyunfei
Ultima modifica di: fscholz,