Array comprehensions
Array comprehensions
非标准。不要使用
数组理解是非标准的。对于面向未来的用途,可以考虑使用Array.prototype.map
,Array.prototype.filter
,箭头的功能,传播语法。
该阵列理解
语法是一个 JavaScript 表达式,它允许您快速组装基于现有的一个新的数组。理解存在于许多编程语言中。
根据 ECMAScript 4 的提议,请参阅下面的 SpiderMonkey 中的旧数组理解语法的差异。
语法
[for (x of iterable) x]
[for (x of iterable) if (condition) x]
[for (x of iterable) for (y of iterable) x + y]
描述
在数组解析中,这两种组件是允许的:
for...of
以及
for-of迭代总是第一个组件。多次迭代或 if 语句被允许。
先前提出的数组理解在 ECMAScript 2016 中是标准化的,它提供了基于另一个内容构建新数组的有用捷径。内涵往往可以拨打电话到的使用map()
和filter()
,或合并两者的一种方式。
以下理解需要一个数字数组,并为每个数字的浮点创建一个新数组的。
var numbers = [1, 2, 3, 4];
var doubled = [for (i of numbers) i * 2];
console.log(doubled // logs 2,4,6,8
这相当于以下map()
操作:
var doubled = numbers.map(i => i * 2
Comprehensions 也可以用来选择符合特定表达式的项目。这是一个只选择偶数的理解:
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
filter()
可以用于相同的目的:
var evens = numbers.filter(i => i % 2 === 0
map()
和filter()
风格的操作可被组合成一个单一的阵列理解。这是一个只过滤偶数的函数,然后创建一个包含他们的双精度的数组:
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
数组理解的方括号为范围目的引入了一个隐含的块。新变量(如示例中的i)被视为已被声明为使用let
。这意味着他们不能在理解之外获得。
数组理解的输入本身不需要是数组; 迭代器和生成器也可以使用。
即使字符串可以用作输入; 以实现上面的过滤器和贴图操作(在类似数组的对象下):
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'
同样,输入表单不会被保留,所以我们必须使用join()
返回到一个字符串。
示例
简单的数组理解
[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], the same as below:
[for (year of years) if (year > 2000 && year < 2010) year];
// [2006]
数组理解与map和filter的对比
理解数组理解语法的一个简单方法是将其与数组map
和filter
方法进行比较:
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]
使用两个数组的数组理解
使用两个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"], 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"]]
规范
最初是在 ECMAScript 2015 草案中,但在修订版 27(2014年8月)中被删除。有关规范语义,请参阅 ES2015 的旧版本。
浏览器兼容性
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | No support | 30 (30) | No support | No support | No support |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | No support | No support | 30.0 (30) | No support | No support | No support |