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

标准库中的新对象和类型-2

标准库中的新对象和类型-2

成员名称JavaScript 支持许多众所周知的成员名称,它们对创建遵循特定于环境模式的对象很有用。一个例子就是                iterator,可使用它在支持迭代行为的对象上命名函数。如果想创建一个伪装成标准 ECMAScript                迭代器的斐波纳契数列生成对象,需要创建一个包含 iterator 函数的对象。但是,由于任何人都能使用该名称,所以                ECMAScript 6 坚持要求您使用 iteratorSymbol 代替:
清单 3.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let fibonacci = {
  [Symbol.iterator]: function*() {
    let pre = 0, cur = 1;
    for (;;) {
      let temp = pre;
      pre = cur;
      cur += temp;
      yield cur;
    }
  }
}
  
for (let n of fibonacci) {
  // truncate the sequence at 1000
  if (n > 1000)
    break;
  console.log(n);
}




同样地,Symbol 的主要功能是帮助程序员避免库之间的名称冲突。这最初有点难掌握,但可以尝试将                Symbol 视为基于它提供的字符串名称的唯一哈希值。
集合类型如果您使用 ECMAScript 超过 10 分钟,您就会知道该语言支持数组——数组自 1.0                版开始就是该规范的核心部分。尽管数组存在限制(最主要的限制是大小固定),但它们能很好地为我们服务;可能在未来数年也是如此。
但我们是时候承认一些事实了,即使我们从不会向任何人提起:数组……不是万能的。
为了帮助收拾残局,ECMAScript 6 向标准 JavaScript 环境添加了两个集合类型:Map 和                Set。
Map 是一组名称/值对,与 ECMAScript 对象非常相似。不同之处在于,Map                包含的方法使它比原始 ECMAScript 对象更容易使用:
  • get() 和 set() 分别查找和设置键/值对
  • clear() 将完全清空集合
  • keys() 返回 Map 中的键的一个可迭代集合
  • values() 对值执行同样的操作
另外,像 Array 一样,Map 包含受函数语言启发的方法,比如                forEach() 在 Map 自身上运行。
清单 4.
1
2
3
4
5
6
7
8
9
let m = new Map();
m.set("key1", "value1");
m.set("key2", "value2");
m.forEach((key, value, map) => {
  console.log(key,"=",value," from ", map);
})

console.log(m.keys());
console.log(m.values());




Set 看起来更像传统的对象集合,因为对象可简单地添加到集合中。但 Set                会依次检查每个对象,以确保它们未与集合中已存在的值重复:
清单 5.
1
2
3
4
5
6
let s = new Set();
s.add("Ted");
s.add("Jenni");
s.add("Athen");
s.add("Ted"); // duplicate!
console.log(s.size); // 3




像 Map 一样,Set 之上也拥有方法,使它可以执行函数式交互,比如                forEach。从根本上讲,Set                像一个数组,但没有尖角括号。它动态增长,而且缺少任何形式的排序机制。如果使用                Set,您不能像数组一样按索引来查找对象。
弱引用ECMAScript 6 还引入了 WeakMaps 和                WeakSets,它们分别是通过弱引用(而不是通过传统的强引用)持有自己的值的 Map 和                Set。ECMAScript 规范非常清楚地描述了 WeakMap                内持有的对象上发生的事;对它的解释同样适用于 WeakSet:
如果一个被用作 WeakMap 键/值对的对象仅能跟随从 WeakMap                内开始的引用链访问,那么这个键/值对就无法访问,会自动从 WeakMap 删除。
本文不再赘述 WeakMaps 和 WeakSets                的效用。它们主要用于库代码(尤其是与缓存相关的代码),在应用程序代码中可能不会过多地出现。
Promise异步操作是 Node.js 的核心部分(通常在事件驱动编程的标签行下),但实现它们向来不轻松。最初,Node.js                    社区似乎决定使用事件订阅,但一段时间后,开发人员都迁移到一种更倾向于回调驱动的风格。这给我们带来了不堪回首的回调地狱,Node.js                代码似乎“布满了”屏幕:
清单 6.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let bookOrder = {'isbn': '978-0375504525', 'qty': 1};

function processBookOrders() {
  setTimeout(function() {
    // pretend this is an async call to an orders database
    console.log('Getting the next order');
    let nextBookOrder = bookOrder;
    setTimeout(function() {
      // pretend this is an async call to a books database
      console.log(`Looking for ISBN ${nextBookOrder.isbn}`);
      if (nextBookOrder.isbn == '978-0375504525') {
        console.log('The book title is \'As I Lay Dying\'');
        // pretend this is an async call to check stock levels
        setTimeout(function() {
          if (nextBookOrder.qty == 1)
            console.log('The book is in stock!');
          else
          console.log('We do not have enough copies of the book in stock.');
        }, 1000); // end of call to check stock levels
      } else
        console.log('This is not a book we carry.');
    }, 1000); // end of call to the books database
  }, 1000); // end of call to the orders database
};

processBookOrders();




这段代码处理一个书店的订单,该书店仅有一本书。处理该订单所需的所有逻辑与多个嵌套函数调用一致。如果这是在实际工作中,每个回调之间可能有许多行代码,使代码非常难理解、调试和维护。
另请注意,对于上面的示例,我使用了两个空格的缩进。想象坚持使用 4 或 8 空格缩进的开发人员对代码的滚动浏览。
经历了大量痛苦和愤怒之后,ECMAScript 社区在异步计算中发布了一种回调的替代方案:现在的标准 Promise                类型。
在 JavaScript 中使用 Promise                是事半功倍的。首先,构建代码来“实现某种用途”(如上面的清单所示)的人现在返回 Promise,而不是使用传统的同步执行或                Node.js 回调语法。这使调用方能使用 Promise 的 then()                方法将顺序调用链接起来,使用 catch() 定义发生失败时应执行的操作:
doSomething.then(function(result) {
  console.log(result); // It did something
}).catch(function(err) {
  console.log(err); // Error
});




在 doSomething() 端,现在可编写代码来生成一个 Promise                实例,实现方法通常是将一个执行异步操作的函数放在 Promise 内:
let promise = new Promise(function(resolve, reject) {
  let result = // do a thing, usually async in nature

  if (success) {
    resolve(result);
  }
  else {
    reject(Error("It didn't work"));
  }
});
返回列表