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 696315 of 数组推导式

  • 版本网址缩略名: Web/JavaScript/Reference/Operators/Array_comprehensions
  • 版本标题: 数组推导式
  • 版本 id: 696315
  • 创建于:
  • 创建者: SphinxKnight
  • 是否是当前版本?
  • 评论

修订内容

{{jsSidebar("Operators")}} {{harmony}}

概述

数组推导式是一种新的 JavaScript 表达式语法,使用它,你可以在一个原有数组的基础上快速的构造出(推导出)一个新的数组。

很多语言中都有推导式语法,现在 JavaScript 中也有了。

语法

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

描述

在数组推导式内部,可以使用下面两种子语句:

每个 for-of 语句都放在与其配对的 if 语句(可以有多个,也可以完全省略)的左边,每个数组推导式中可以包含多组这样的配对,但最终选取的表达式值只能有一个,且这个值(也可以是个数组推导式,也就是说可以嵌套)只能放在推导式的最右边,紧靠着右中括号。

示例

基本的数组推导式写法

[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" ]

带有 if 语句的数组推导式

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], 和下面的写法等效:

[for (year of years) if (year > 2000 && year < 2010) year];
// [ 2006] 

用数组推导式比用数组的 mapfilter 方法更简洁

对比数组的 {{jsxref("Array.map", "map")}} 和 {{jsxref("Array.filter", "filter")}} 方法:

var numbers = [ 1, 2, 3 ];

numbers.map(function (i) { return i * i });
[for (i of numbers) i*i ];
// 返回值都是 [ 1, 4, 9 ]

numbers.filter(function (i) { return i < 3 });
[for (i of numbers) if (i < 3) i];
// 返回值都是 [ 1, 2 ]

带有两个数组的数组推导式

用两个 for-of 语句迭代两个不同的数组:

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"],和下面的写法等效:

[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"]],和下面的写法不等效:

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

规范

规范名称及链接 规范状态
{{SpecName('ES6', '#sec-array-comprehension', 'Array comprehensions')}} {{Spec2('ES6')}}

浏览器兼容性

{{ 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 目前实现的推导式特性存在的问题

  • 还不能在推导式中使用解构 ({{bug(980828)}}).

SpiderMonkey 目前实现的 ES6 推导式和之前实现的 ES4 推导式(JS1.7/JS1.8)的区别

  • ES6 推导式中的 for-of 语句会为每次迭代分配一个新的作用域:
    • 旧写法:[()=>x for (x of [0, 1, 2])][1]() // 2
    • 新写法:[for (x of [0, 1, 2]) ()=>x][1]() // 1, 每个闭包都引用了一个不同的上层变量 x
  • ES6 推导式要求最终选取的表达式值放在最右边,而不是最左边,这样更符合英语的阅读习惯:
    • 旧写法:[i * 2 for (i of numbers)]
    • 新写法:[for (i of numbers) i * 2]
  • ES6 推导式中可以包含多个 for 语句和 if 语句,以前都只能写一个。
  • ES6 推导式中只能使用 for...of 语句,以前还可以使用 for...in

相关链接

  • for...of
  • {{jsxref("Operators/Generator_comprehensions", "生成器推导式", "" ,1)}}

修订版来源

<p>{{jsSidebar("Operators")}} {{harmony}}</p>
<h2 id=".E6.A6.82.E8.BF.B0">概述</h2>
<p><span class="seoSummary"><strong>数组推导式</strong>是一种新的 JavaScript 表达式语法,使用它,你可以在一个原有数组的基础上快速的构造出(推导出)一个新的数组。</span></p>
<p><span>很多语言中都有推导式语法,现在 JavaScript 中也有了。</span></p>
<h2 id=".E8.AF.AD.E6.B3.95">语法</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=".E6.8F.8F.E8.BF.B0">描述</h2>
<p>在数组推导式内部,可以使用下面两种子语句:</p>
<ul>
 <li><a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of">for...of</a></li>
 <li><a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/if...else">if</a></li>
</ul>
<p>每个 <code>for-of</code> 语句都放在与其配对的 <code>if</code> 语句(可以有多个,也可以完全省略)的左边,每个数组推导式中可以包含多组这样的配对,但最终选取的表达式值只能有一个,且这个值(也可以是个数组推导式,也就是说可以嵌套)只能放在推导式的最右边,紧靠着右中括号。</p>
<h2 id=".E7.A4.BA.E4.BE.8B">示例</h2>
<h3 id=".E5.9F.BA.E6.9C.AC.E7.9A.84.E6.95.B0.E7.BB.84.E6.8E.A8.E5.AF.BC.E5.BC.8F.E5.86.99.E6.B3.95">基本的数组推导式写法</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=".E5.B8.A6.E6.9C.89_if_.E8.AF.AD.E5.8F.A5.E7.9A.84.E6.95.B0.E7.BB.84.E6.8E.A8.E5.AF.BC.E5.BC.8F">带有 if 语句的数组推导式</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], 和下面的写法等效:

[for (year of years) if (year &gt; 2000 &amp;&amp; year &lt; 2010) year];
// [ 2006] 
</pre>
<h3 id=".E7.94.A8.E6.95.B0.E7.BB.84.E6.8E.A8.E5.AF.BC.E5.BC.8F.E6.AF.94.E7.94.A8.E6.95.B0.E7.BB.84.E7.9A.84_map.E3.80.81filter_.E6.96.B9.E6.B3.95.E6.9B.B4.E7.AE.80.E6.B4.81">用数组推导式比用数组的 <code>map</code>、<code>filter</code> 方法更简洁</h3>
<p>对比数组的 {{jsxref("Array.map", "map")}} 和 {{jsxref("Array.filter", "filter")}} 方法:</p>
<pre class="brush: js">
var numbers = [ 1, 2, 3 ];

numbers.map(function (i) { return i * i });
[for (i of numbers) i*i ];
// 返回值都是 [ 1, 4, 9 ]

numbers.filter(function (i) { return i &lt; 3 });
[for (i of numbers) if (i &lt; 3) i];
// 返回值都是 [ 1, 2 ]
</pre>
<h3 id=".E5.B8.A6.E6.9C.89.E4.B8.A4.E4.B8.AA.E6.95.B0.E7.BB.84.E7.9A.84.E6.95.B0.E7.BB.84.E6.8E.A8.E5.AF.BC.E5.BC.8F">带有两个数组的数组推导式</h3>
<p>用两个 <code>for-of</code> 语句迭代两个不同的数组:</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"],和下面的写法<strong>等效</strong>:

[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"]],和下面的写法<strong>不等效</strong>:

[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=".E8.A7.84.E8.8C.83">规范</h2>
<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">规范名称及链接</th>
   <th scope="col">规范状态</th>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-array-comprehension', 'Array comprehensions')}}</td>
   <td>{{Spec2('ES6')}}</td>
  </tr>
 </tbody>
</table>
<h2 id=".E6.B5.8F.E8.A7.88.E5.99.A8.E5.85.BC.E5.AE.B9.E6.80.A7">浏览器兼容性</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>
<h3 id="SpiderMonkey_.E7.9B.AE.E5.89.8D.E5.AE.9E.E7.8E.B0.E7.9A.84.E6.8E.A8.E5.AF.BC.E5.BC.8F.E7.89.B9.E6.80.A7.E5.AD.98.E5.9C.A8.E7.9A.84.E9.97.AE.E9.A2.98">SpiderMonkey 目前实现的推导式特性存在的问题</h3>
<ul>
 <li>还不能在推导式中使用解构 ({{bug(980828)}}).</li>
</ul>
<h3 id="SpiderMonkey_.E7.9B.AE.E5.89.8D.E5.AE.9E.E7.8E.B0.E7.9A.84_ES6_.E6.8E.A8.E5.AF.BC.E5.BC.8F.E5.92.8C.E4.B9.8B.E5.89.8D.E5.AE.9E.E7.8E.B0.E7.9A.84_ES4_.E6.8E.A8.E5.AF.BC.E5.BC.8F.EF.BC.88JS1.7.2FJS1.8.EF.BC.89.E7.9A.84.E5.8C.BA.E5.88.AB">SpiderMonkey 目前实现的 ES6 推导式和之前实现的 ES4 推导式(JS1.7/JS1.8)的区别</h3>
<ul>
 <li>ES6 推导式中的 <code>for-of</code> 语句会为每次迭代分配一个新的作用域:
  <ul>
   <li>旧写法:<code>[()=&gt;x for (x of [0, 1, 2])][1]() // 2</code></li>
   <li>新写法:<code>[for (x of [0, 1, 2]) ()=&gt;x][1]() // 1, 每个闭包都引用了一个不同的上层变量 x</code></li>
  </ul>
 </li>
 <li>ES6 推导式要求最终选取的表达式值放在最右边,而不是最左边,这样更符合英语的阅读习惯:
  <ul>
   <li>旧写法:<code>[i * 2 for (i of numbers)]</code></li>
   <li>新写法:<code>[for (i of numbers) <code>i * 2</code>]</code></li>
  </ul>
 </li>
 <li>ES6 推导式中可以包含多个 <code>for</code> 语句和 <code>if</code> 语句,以前都只能写一个。</li>
 <li>ES6 推导式中只能使用 <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of">for...of</a></code> 语句,以前还可以使用 <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/for...in">for...in</a></code>。</li>
</ul>
<h2 id="See_also" name="See_also">相关链接</h2>
<ul>
 <li><a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of"><code>for...of</code></a></li>
 <li>{{jsxref("Operators/Generator_comprehensions", "生成器推导式", "" ,1)}}</li>
</ul>
恢复到这个版本