首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

ECMAScript 6 中的函数增强-4

ECMAScript 6 中的函数增强-4

斐波纳契数列(全球每种函数语言的 “Hello World” 等效程序)就是这样一个无限流:
清单 19. 斐波纳契数的无限流
var fibo = (function() {
  var prev1 = undefined;
  var prev2 = undefined;
  return function() {
    if (prev1 == undefined && prev2 == undefined) {
      prev1 = 0;
      return 0;
    }
    if (prev1 == 0 && prev2 == undefined) {
      prev1 = 1;
      prev2 = 0;
      return 1;
    }
    else {
      var ret = prev1 + prev2;
      prev2 = prev1;
      prev1 = ret;
      return ret;
    }
  };
})();




无限流 是一个从不会用完要返回的值的流。在这种情况下,斐波拉契数列没有逻辑终点。
JavaScript 中的反应式编程非常复杂。如果您打算了解更多的信息,可以访问           GitHub 页面。

尽管起初看起来很奇怪,但无限流的概念是其他一些基于 ECMAScript        的有趣技术(比如反应式编程)的核心。想想如果我们将用户事件(比如移动鼠标、单击按钮和按键)视为无限流,函数从流中获取每个事件并进行处理,结果会怎样?
构建无限流所需的代码量非常大,所以 ECMAScript 6 定义了一种新语法(和一个新关键字)来让代码更加简洁。在这里可以看到,我重写了清单 17 中的示例:
清单 20. 一个使用生成器的有限值流
function* getName() {
  yield "Ted";
  yield "Charlotte";
  yield "Michael";
  yield "Matthew";
}
let names = getName();
console.log(names.next().value);
console.log(names.next().value);
console.log(names.next().value);
console.log(names.next().value);
console.log(names.next().value);




同样地,该函数将按顺序打印出每个名称。当它用完所有名称时,它会不停地打印 “undefined”。在语法上,yield 关键字看起来类似于        return,但事实上,它表示 “返回但记住我在此函数中的位置,以便下次调用它时,从离开的位置开始执行。”这显然比传统的 return 更复杂。
生成器的使用与第一个示例稍微不同:我们捕获了 getName 函数的返回值,然后像迭代器一样使用该对象。这是 ECMAScript 6        中的一个特意的设计决定。从技术上讲,生成器函数返回一个 Generator 对象,该对象用于从生成器函数获取各个值。新语法旨在尽可能地模拟迭代器。
谈到迭代器,还有最后一个需要知道的语法更改。
for-of 关键字经典的 for 循环在 ECMAScript 6 具有了新形式,这是由于添加了一个辅助关键字:of。在许多方面,新语法与          for-in 没多大区别,但它支持生成器函数。
返回到清单 19 中的斐波纳契数列,这是向函数添加 for-of 关键字时发生的情况:
清单 21. 斐波纳契数列中的 ‘for        of’
function* fibo() { // a generator function
  yield 0;
  yield 1;
  let [prev, curr] = [0, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  console.log(n);
   
  // By the way, this is an infinite stream, so this loop
  // will never terminate unless you break out of it
}




for-of 和 for-in 之间存在着细微区别,但在大多数情况下,您可以使用 for-of        直接取代旧语法。它添加了隐式使用生成器的能力 — 就像我们在无限流示例中使用 getName() 执行的操作一样。
结束语现在,您已注意到 ECMAScript 6 绝对不是一个简单的勘误版本。我们这里介绍的许多功能都源自函数编程概念,但不要被这种现象所欺骗:ECMAScript 6        远不止是一种函数语言。采用一些函数功能可以使编写 ECMAScript 代码变得更容易,但要实现此目的,您不需要知道单子 (monads)、独异点 (monoids)        和范畴论。在大多数情况下,流行的态度是:如果它适合您,则使用它;如果不适合,还有其他许多选择。
所以如果您从未执行过任何函数编程,不要紧张 — 您可以对 ECMAScript 6 浅尝辄止,绝不会深陷其中。
无论如何,本系列的下一篇文章又会让我们回到原点,介绍 ECMAScript 6 中新的基于类的语法和对象增强。
返回列表