非常教程

JavaScript参考手册

Operators

Generator comprehensions

非标。不使用!

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

生成器解析语法是一个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 and
  • if

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

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

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

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

var doubles = [for (i in it) i * 2];

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

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

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

var result = doSomething(for (i in it) i * 2);

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

示例

Simple generator comprehensions

(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语句的生成器解析

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:简单的生成器。

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生成器。

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特定的实现说明

  • let因为let目前只支持JS版本1.7和XUL脚本标记,所以不支持标识符。
  • 解析中的解构不被支持(错误980828)。

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

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

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

(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迭代,而不适用于迭代。
JavaScript

JavaScript 是一种高级编程语言,通过解释执行,是一门动态类型,面向对象(基于原型)的解释型语言。它已经由ECMA(欧洲电脑制造商协会)通过 ECMAScript 实现语言的标准化。它被世界上的绝大多数网站所使用,也被世界主流浏览器( Chrome、IE、FireFox、Safari、Opera )支持。JavaScript 是一门基于原型、函数先行的语言,是一门多范式的语言,它支持面向对象编程,命令式编程,以及函数式编程。它提供语法来操控文本、数组、日期以及正则表达式等,不支持 I/O,比如网络