首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Generator comprehensions

非标。不使用!

生成器解析是非标准的,它不太可能被添加到ECMAScript中,对于面向未来的用法,请考虑使用生成器。

生成器解析语法是一个JavaScript表达式,它允许您快速组装基于现有迭代对象上一个新的生成功能。理解存在于许多编程语言中。

根据ECMAScript 4的提议,请参阅下面的SpiderMonkey中的旧生成器表达式语法的差异。

句法

代码语言: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 and
  • if

for-of迭代总是第一个组件。多重for-of迭代或if语句被允许。

数组理解的一个显着缺点是它们导致整个新数组在内存中被构造。当理解的输入本身就是一个小数组时,所涉及的开销不大 - 但是当输入是一个大数组或者一个昂贵的(或者确实是无限的)生成器时,创建一个新数组可能会产生问题。

生成器启用序列的延迟计算,并根据需要按需计算项目。发生器理解在语法上几乎与数组理解相同 - 它们使用圆括号而不是大括号 - 但不是构建数组,而是创建一个可以执行延迟的生成器。您可以将它们视为创建生成器的简短语法。

假设我们有一个it遍历大整数序列的迭代器。我们想要创建一个迭代器来迭代他们的doubles。数组理解将在内存中创建一个包含doubled值的完整数组:

代码语言:javascript
复制
var doubles = [for (i in it) i * 2];

另一方面,生成器理解会创建一个新的迭代器,在需要时可根据需要创建双倍的值:

代码语言:javascript
复制
var it2 = (for (i in it) i * 2);
console.log(it2.next()); // The first value from it, doubled
console.log(it2.next()); // The second value from it, doubled

当生成器理解被用作函数的参数时,用于函数调用的括号意味着可以省略外部圆括号:

代码语言:javascript
复制
var result = doSomething(for (i in it) i * 2);

这两个例子之间的显着差异在于,通过使用生成器理解,您只需循环遍历'obj'结构一次,全部,而不是一次理解数组,再循环遍历它。

示例

Simple generator comprehensions

代码语言:javascript
复制
(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"

使用if语句的生成器解析

代码语言:javascript
复制
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

与生成器解析相比较的生成器函数

理解生成器理解语法的一种简单方法是将其与生成器函数进行比较。

例1:简单的生成器。

代码语言:javascript
复制
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]

示例2:使用if生成器。

代码语言:javascript
复制
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]

规范

生成器解析最初在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

SpiderMonkey特定的实现说明

与较老的JS1.7/JS1.8的解析不同

从Gecko 46中删除JS1.7/JS1.8的解析(bug 1220564)。

旧的解析语法(不再使用!):

代码语言:javascript
复制
(X for (Y in Z))
(X for each (Y in Z))
(X for (Y of Z))

区别:

  • ES7理解为每个“for”节点创建一个范围,而不是作为一个整体理解。
    • 旧: [...(()=>x for (x of [0, 1, 2]))][1]() // 2
    • 新: [...(for (x of [0, 1, 2]) ()=>x)][1]() // 1, each iteration creates a fresh binding for x.
  • ES7的理解从“for”开始,而不是赋值表达式。
    • 旧: (i * 2 for (i of numbers))
    • 新: (for (i of numbers) i * 2)
  • ES7内涵可以有多个iffor组件。
  • ES7理解仅适用for...offor...in迭代,而不适用于迭代。

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com