Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 913001 of Array comprehensions

  • Revision slug: Web/JavaScript/Reference/Operators/Array_comprehensions
  • Revision title: Array comprehensions
  • Revision id: 913001
  • Created:
  • Creator: so_matt_basta
  • Is current revision? No
  • Comment

Revision Content

{{jsSidebar("Operators")}} {{es7}}

The array comprehension syntax is a JavaScript expression which allows you to quickly assemble a new array based on an existing one. Comprehensions exist in many programming languages and the upcoming ECMAScript 7 standard defines array comprehensions for JavaScript.

See below for differences to the old array comprehension syntax in SpiderMonkey, based on proposals for ECMAScript 4.

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.

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

{{WhyNoSpecStart}}Was initially in the ECMAScript 6 draft, but got removed in revision 27 (August 2014). Please see older revisions of ES 6 for specification semantics. An updated version is expected to be in a new ES2016 / ES7 draft.{{WhyNoSpecEnd}}

Browser compatibility

{{CompatibilityTable}}

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support {{CompatNo}} {{ CompatGeckoDesktop("30") }} {{CompatNo}} {{CompatNo}} {{CompatNo}}
Feature Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support {{CompatNo}} {{CompatNo}} {{ CompatGeckoMobile("30") }} {{CompatNo}} {{CompatNo}} {{CompatNo}}

SpiderMonkey-specific implementation notes

  • {{jsxref("Statements/let", "let")}} as an identifier is not supported as let is currently only available to JS version 1.7 and XUL scripts tags.
  • Destructuring in comprehensions is not supported yet ({{bug(980828)}}).

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

  • ES7 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.
  • ES7 comprehensions start with "for" instead of the assignment expression.
    • Old: [i * 2 for (i of numbers)]
    • New: [for (i of numbers) i * 2]
  • ES7 comprehensions can have multiple if and for components.
  • ES7 comprehensions only work with {{jsxref("Statements/for...of", "for...of")}} and not with {{jsxref("Statements/for...in", "for...in")}} iterations.

See also

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

Revision Source

<div>{{jsSidebar("Operators")}} {{es7}}</div>

<p>The <strong>array comprehension</strong> syntax is a JavaScript expression which allows you to quickly assemble a new array based on an existing one. Comprehensions exist in many programming languages and the upcoming ECMAScript 7 standard defines array comprehensions for JavaScript.</p>

<p>See <a href="#Differences_to_the_older_JS1.7.2FJS1.8_comprehensions">below</a> for differences to the old array comprehension syntax in SpiderMonkey, based on proposals for ECMAScript 4.</p>

<h2 id="Syntax">Syntax</h2>

<pre class="syntaxbox">
[for (x of iterable) x]
[for (x of iterable) if (condition) x]
[for (x of iterable) for (y of iterable) x + y]
</pre>

<h2 id="Description">Description</h2>

<p>Inside array comprehensions, these two kinds of components are allowed:</p>

<ul>
 <li>{{jsxref("Statements/for...of", "for...of")}} and</li>
 <li>{{jsxref("Statements/if...else", "if")}}</li>
</ul>

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

<h2 id="Examples">Examples</h2>

<h3 id="Simple_array_comprehensions">Simple array comprehensions</h3>

<pre class="brush:js">
[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" ]</pre>

<h3 id="Array_comprehensions_with_if_statement">Array comprehensions with if statement</h3>

<pre class="brush: js">
var years = [ 1954, 1974, 1990, 2006, 2010, 2014 ];
[for (year of years) if (year &gt; 2000) year];
// [ 2006, 2010, 2014 ]
[for (year of years) if (year &gt; 2000) if(year &lt; 2010) year];
// [ 2006], the same as below:
[for (year of years) if (year &gt; 2000 &amp;&amp; year &lt; 2010) year];
// [ 2006] 
</pre>

<h3 id="Array_comprehensions_compared_to_map_and_filter">Array comprehensions compared to <code>map</code> and <code>filter</code></h3>

<p>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:</p>

<pre class="brush: js">
var numbers = [ 1, 2, 3 ];

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

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

<h3 id="Array_comprehensions_with_two_arrays">Array comprehensions with two arrays</h3>

<p>Using two for-of iterations to work with two arrays:</p>

<pre class="brush: js">
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 &gt; 1) for (j of letters) if(j &gt; "a") i+j]
// ["2b", "2c", "3b", "3c"], the same as below:

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

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

[for (i of numbers) [for (j of letters) if (i &gt; 1) if(j &gt; "a") i+j]]
// [[], ["2b", "2c"], ["3b", "3c"]]
</pre>

<h2 id="Specifications">Specifications</h2>

<p>{{WhyNoSpecStart}}Was initially in the ECMAScript 6 draft, but got removed in revision 27 (August 2014). Please see older revisions of ES 6 for specification semantics. An updated version is expected to be in a new ES2016 / ES7 draft.{{WhyNoSpecEnd}}</p>

<h2 id="Browser_compatibility">Browser compatibility</h2>

<p>{{CompatibilityTable}}</p>

<div id="compat-desktop">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Feature</th>
   <th>Chrome</th>
   <th>Firefox (Gecko)</th>
   <th>Internet Explorer</th>
   <th>Opera</th>
   <th>Safari</th>
  </tr>
  <tr>
   <td>Basic support</td>
   <td>{{CompatNo}}</td>
   <td>{{ CompatGeckoDesktop("30") }}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
  </tr>
 </tbody>
</table>
</div>

<div id="compat-mobile">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Feature</th>
   <th>Android</th>
   <th>Chrome for Android</th>
   <th>Firefox Mobile (Gecko)</th>
   <th>IE Mobile</th>
   <th>Opera Mobile</th>
   <th>Safari Mobile</th>
  </tr>
  <tr>
   <td>Basic support</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{ CompatGeckoMobile("30") }}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
  </tr>
 </tbody>
</table>
</div>

<h2 id="SpiderMonkey-specific_implementation_notes">SpiderMonkey-specific implementation notes</h2>

<ul>
 <li>{{jsxref("Statements/let", "let")}} as an identifier is not supported as <code>let</code> is currently only available to JS version 1.7 and XUL scripts tags.</li>
 <li>Destructuring in comprehensions is not supported yet ({{bug(980828)}}).</li>
</ul>

<h2 id="Differences_to_the_older_JS1.7JS1.8_comprehensions">Differences to the older JS1.7/JS1.8 comprehensions</h2>

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

<h2 id="See_also">See also</h2>

<ul>
 <li>{{jsxref("Statements/for...of", "for...of")}}</li>
 <li>{{jsxref("Operators/Generator_comprehensions", "Generator comprehensions", "" ,1)}}</li>
</ul>
Revert to this revision