TypeScript實戰指南》—2.1.7 iterator和generator

      網友投稿 688 2025-03-31

      2.1.7 iterator和generator


      1. iterator

      當一個對象實現了Symbol.iterator時,我們認為它是可迭代的。如array、map、set、string、int32Array、uint32Array等一些內置的類型,目前都已經實現了各自的Symbol.iterator。對象上的Symbol.iterator函數負責返回供迭代的值。

      for..of語句會遍歷可迭代的對象,調用對象上的Symbol.iterator方法。

      比如下面是在數組上使用for..of的例子:

      const array = [233, "hello", true];

      for (let value of array) {

      console.log(value); // 233, "hello", true

      }

      for..of和for..in都可以迭代一個數組,但它們之間的區別很大。最明顯的區別莫過于它們用于迭代器的返回值并不相同,for..in迭代的是對象的鍵,而for..of迭代的是對象的值。

      我們可以從下面的例子中看出兩者之間的區別:

      const array = [3, 4, 5];

      for (let i in array) {

      console.log(i); // 0, 1, 2

      }

      for (let i of array) {

      console.log(i); // 4, 5, 6

      }

      另一個區別在于,for..in可以操作任何對象,提供了查看對象屬性的一種方法。但是for..of關注迭代對象的值,內置對象Map和Set已經實現了Symbol.iterator方法,讓我們可以訪問它們的值:

      const fruits = new Set(["apple", "pear", "mango"]);

      fruits["peach"] = "Princess Peach! Make a wish!";

      for (let fruit in fruits) {

      console.log(fruit); // "peach"

      }

      for (let fruit of fruits) {

      console.log(fruit); // "apple", "pear", "peach"

      }

      但這樣的特性僅僅在 ES 6 及以上才上生效。

      當我們將 TypeScript 的代碼生成目標設定為ES5或ES3,迭代器就只允許在array類型上使用。在非數組值上使用for..of語句會得到一個錯誤。即便這些非數組值已經實現了Symbol.iterator屬性,也是不可以的。

      編譯器會生成一個簡單的for循環作為for..of循環,比如:

      const numbers = [1, 2, 3];

      for (let number of numbers) {

      console.log(number);

      }

      生成的代碼為:

      var numbers = [1, 2, 3];

      for (var _i = 0; _i < numbers.length; _i++) {

      var number = numbers[_i];

      console.log(number);

      }

      2. generator

      function * 是用來創建? generator 函數的語法。(在 MDN 的文檔中 generator 稱為生成器。)

      調用 generator 函數時會返回一個generator 對象。generator 對象遵循迭代器接口,即通常所見到的 next、return 和 throw 函數。

      generator函數用于創建懶迭代器,例如下面的這個函數可以返回一個無限整數的列表:

      function* infiniteList() {

      let i = 0;

      while(true) {

      yield i++;

      }

      }

      var iterator = infiniteList();

      while (true) {

      console.log(iterator.next()); // { value: xxxx, done: false }

      }

      當然,也可以設定某個條件終止它,而不只是永遠循環下去。如下所示:

      function* infiniteList(){

      let i = 0;

      while(i < 3)

      yield i++;

      }

      let gen = infiniteList();

      console.log(gen.next()); // { value: 0, done: false }

      console.log(gen.next()); // { value: 1, done: false }

      console.log(gen.next()); // { value: 2, done: false }

      console.log(gen.next()); // { value: undefined, done: true }

      可以說這個設定是generator中最令人興奮的部分。它在實質上允許一個函數可以暫停執行,比如當我們執行了第一次的 gen.next() 后,可以先去做別的事,再回來繼續執行 gen.next(),這樣剩余函數的控制權就交給了調用者。

      當你直接調用 generator 函數時,它并不會執行,它只會創建一個 generator 對象。

      在下面的例子中,我們可以看到一個更靈活的使用方式:

      function* generator(){

      console.log('Execution started');

      yield 0;

      console.log('Execution resumed');

      yield 1;

      console.log('Execution end');

      }

      執行它,則會看到如下輸出結果:

      constiterator = generator();

      console.log(iterator.next());

      // "Execution started"

      // { value: 0, done: false }

      console.log(iterator.next()); // { value: 1, done: false }

      // "Execution resumed'"

      // { value: 1, done: false }

      console.log(iterator.next());

      // "Execution end"

      // { value: undefined, done: true }

      console.log(iterator.next());

      // { value: undefined, done: true }

      從上面代碼可以得知:

      generator 對象只會在調用next時開始執行。

      函數在執行到yield語句時會暫停并返回yield的值。

      函數在next被調用時繼續恢復執行。

      《TypeScript實戰指南》—2.1.7 iterator和generator

      所以實質上generator函數的執行與否是由外部的 generator 對象控制的。

      不過除了 yield 傳值到外部,我們也可以通過 next 傳值到內部進行調用。下面的例子展示了iterator.next傳值的方式:

      function* generator() {

      const who = yield;

      console.log('hello '+ who); // bar!

      }

      const iterator = generator();

      Console.log(iterator.next());

      // {value: undefined, done: false}

      console.log(iterator.next('TypeScript'));

      // hello TypeScript

      // {value: undefined, done: true}

      以上便是 next 和 return 函數的內容,接下來我們來看一下 throw 函數如何處理迭代器內部報錯。

      下面是iterator.throw的例子:

      function* generator() {

      try {

      yield 1;

      }

      catch(error) {

      console.log(error.message);

      }

      }

      const iterator = generator();

      iterator.next()

      // {value: 1, done: false}

      iterator.throw(new Error('something incorrect'));

      // something incorrect

      // {value: undefined, done: true}

      通過以上的案例我們可以得知,外部是可以對 generator 內部進行干涉的:

      外部系統可以傳遞一個值到 generator 函數體中。

      外部系統可以拋入一個異常到 generator 函數體中。

      Generator TypeScript

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel2007怎么插入數據透視表?
      下一篇:怎么把表格里的小數點設置留2位(怎么讓表格小數點保留兩位)
      相關文章
      亚洲日韩国产精品乱-久| 亚洲成AV人片天堂网无码| 亚洲熟妇中文字幕五十中出| 亚洲成aⅴ人片久青草影院按摩| 91嫩草亚洲精品| 亚洲黄色网站视频| 亚洲视频在线播放| 久久亚洲春色中文字幕久久久 | 精品国产日韩亚洲一区| 亚洲av再在线观看| 国产精品亚洲一区二区三区久久 | 亚洲精品理论电影在线观看| 亚洲一区在线免费观看| 亚洲精品国产福利在线观看| 亚洲国产成人精品无码区在线秒播 | 国产精品亚洲片在线花蝴蝶| 国产精品亚洲片在线花蝴蝶| www.亚洲精品.com| 亚洲国产精品成人一区| 亚洲人成无码www久久久| 91麻豆国产自产在线观看亚洲| 国产亚洲美日韩AV中文字幕无码成人| 国产成人精品曰本亚洲79ren| 国产成人精品日本亚洲专区61| 亚洲一区二区三区影院| 亚洲精品无码久久久影院相关影片| 亚洲免费人成在线视频观看| 国产AV无码专区亚洲AV毛网站| 久久久亚洲精品视频| 4444亚洲国产成人精品| 亚洲免费观看在线视频| 亚洲第一区二区快射影院| 亚洲精品乱码久久久久久蜜桃图片| 欧洲亚洲综合一区二区三区| 亚洲精品黄色视频在线观看免费资源 | 亚洲成人在线网站| 亚洲国产精品一区二区久| 亚洲www在线观看| 亚洲国产欧美日韩精品一区二区三区| 色偷偷噜噜噜亚洲男人| 亚洲情a成黄在线观看|