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

ECMAScript 6 中的函数增强-3

ECMAScript 6 中的函数增强-3

词法 ‘this’ 绑定为了解决与 this 相关的定义问题,箭头函数拥有所谓的词法 this 绑定。这意味着箭头函数在定义函数时使用          this 值,而不是在执行它时。
采用规则:完全理解新 this 规则可能需要一段时间。新箭头函数规则并不总是这么直观。作为开发人员,可以计划对          “内联” 函数使用箭头函数,对方法使用传统函数。如果这么做,各个方面都应按预期工作。

或许理解这一区别的最简单方法是借助一个旧的 Node.js 对象 EventEmitter。回想一下,EventEmitter(获取自 events        模块)是一个简单的发布-订阅式消息系统:您可以在某个特定事件名称上的发射器上注册回调,当该事件被 “发出” 时,则按注册的顺序触发回调。
如果向 EventEmitter 注册一个遗留函数,捕获的 this 将是在运行时确定的参数。但是如果您向 EventEmitter          注册一个箭头函数,this 将在定义箭头函数时绑定:
清单 15. ‘this’        被箭头函数绑定
let EventEmitter = require('events');
let ee = new EventEmitter();
ee.on('event', function() {
  console.log("function event fired", this);
});
ee.on('event', () => {
  console.log("arrow event fired", this);
});
var bob = {
  firstName: "Bob",
  lastName: "Robertson"
};
bob.handleEventLegacy = function() {
  console.log("function event fired", this);
};
bob.handleEventArrow = () => {
  console.log("arrow event fired", this);
};
ee.on('event', bob.handleEventLegacy);
ee.on('event', bob.handleEventArrow);
ee.emit('event');




在触发函数事件时,this 被绑定到 EventEmitter 本身,而箭头事件未绑定到任何目标(它们分别打印一个空对象)。
生成器函数生成器函数旨在生成一个值流供其他方使用。许多函数语言都使用了生成器,它们在其中可能名为序列。现在 ECMAScript        中也引入了它们。
要了解生成器的实际工作原理,需要稍作解释。首先,想象一组简单的名称:
清单 16. 一个简单的集合
var names = ["Ted", "Charlotte", "Michael", "Matthew"];




现在假设我们希望一个函数返回每个名称,每个函数调用一次返回一个名称,直到全部返回:
清单 17. 一个返回每个名称的函数
var getName = (function() {
  var current = 0;
  return function() {
    if (current > names.length)
      return undefined;
    else {
      var temp = names[current];
      current++;
      return temp;
    }
  };
})();
console.log(getName()); // prints Ted
console.log(getName()); // prints Charlotte
console.log(getName()); // prints Michael
console.log(getName()); // prints Matthew
console.log(getName()); // prints undefined




起初,上面的函数返回函数的方式可能看起来很陌生。这是必要的,因为 getName 函数需要在多个函数调用中跟踪它的状态。在类似 C        的语言中,可以将状态存储在 getName 函数内的静态变量中,但像类似的 Java 和 C# 一样,ECMAScript        不支持在函数中使用静态变量。在这种情况下,我们将使用闭包,以便函数字面量在返回后继续绑定到 “当前” 变量,使用该变量存储自己的状态。
要理解的重要一点是,此函数不会一次获取一个有限的值序列(采用返回数组的形式),它一次获取一个元素,直到没有剩余的元素。
但是如果要返回的元素永远用不完,该怎么办?
函数编程中的无限流与在名称数组上使用迭代器相比,似乎前面的代码示例没有多大改进。毕竟,这就是迭代器的用途:让各个元素能够访问一个集合的内容。重要的变化表现在原始数组不再可见,甚至不再是数组时:
清单 18. 一个有限的流
var getName = (function() {
  var current = 0;
  return function() {
    switch (current++) {
      case 0: return "Ted";
      case 1: return "Charlotte";
      case 2: return "Michael";
      case 3: return "Matthew";
      default: return undefined;
    }
  };
})();




从技术上讲,您看到的仍是一个迭代器,但它的实现看起来与来自样本的迭代器截然不同;这里没有集合,只有一组硬编码的值。
从本质上讲,它是一个没有关联集合的迭代器,这突出了一个重要的事实:我们的函数生成的值的来源          现在深度封装在离调用方很远的地方。这进而引入了一个更有趣的想法:调用方可能不知道最初没有集合,不知道生成的值永无止境。这就是一些语言所称的无限流
返回列表