ES6 系列八:Iterator

"Code tailor",爲前端開發者提供技術相關資訊以及系列基礎文章,微信關注「小和山的菜鳥們」公衆號,及時獲取最新文章。

前言

在開始學習以前,咱們想要告訴您的是,本文章是對阮一峯《ECMAScript6 入門》一書中 "Iterator" 章節的總結,若是您已掌握下面知識事項,則可跳過此環節直接進入題目練習javascript

  • 什麼是 Iterator?有何做用?
  • Iterator 是如何遍歷的?
  • 默認的 Iterator 的接口和經常使用場合有哪些?

若是您對某些部分有些遺忘,👇🏻 已經爲您準備好了!前端

學習連接

Iterator 的學習java

彙總總結

概念和做用

JavaScript 表示「集合」的數據結構,主要是數組(Array)、對象(Object),Map Set。用戶能夠組合使用它們,定義本身的數據結構,好比數組的成員是 MapMap 的成員是對象。這樣就須要一種統一的接口機制,來處理全部不一樣的數據結構。es6

遍歷器( Iterator)就是這樣一種機制。它是一種接口,爲各類不一樣的數據結構提供統一的訪問機制。任何數據結構只要部署 Iterator 接口,就能夠完成遍歷操做(即依次處理該數據結構的全部成員)。

做用:數組

  • 爲各類數據結構,提供一個統一的、簡便的訪問接口
  • 使得數據結構的成員可以按某種次序排列
  • ES6 創造了一種新的遍歷命令 for...of 循環,Iterator 接口主要供 for...of 進行遍歷循環。

遍歷過程

  1. 建立一個指針對象,指向當前數據結構的起始位置。也就是說,遍歷器對象本質上,就是一個指針對象。
  2. 第一次調用指針對象的 next 方法,能夠將指針指向數據結構的第一個成員。
  3. 第二次調用指針對象的 next 方法,指針就指向數據結構的第二個成員。
  4. 不斷調用指針對象的 next 方法,直到它指向數據結構的結束位置。

默認 Iterator 接口

Iterator 接口的目的,就是爲全部數據結構,提供了一種統一的訪問機制,即 for...of 循環。當使用 for...of 循環遍歷某種數據結構時,該循環會自動去尋找 Iterator 接口。一種數據結構只要部署了 Iterator 接口,咱們就稱這種數據結構是「可遍歷的」。微信

在 ES6 中有如下幾個數據結構具備原生的 Iterator 接口,也就是說,這些數據結構能夠直接調用 for...of 進行遍歷數據結構

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 函數的 arguments 對象
  • NodeList 對象

除了上面這些數據結構,若是須要在別的數據結構中(主要爲 Object)調用 for...of,則須要本身在 Symbol.iterator 屬性上面部署,這樣纔會被 for...of 循環遍歷。定義方式舉例以下:函數

const obj = {
  [Symbol.iterator]: function () {
    return {
      next: function () {
        return {
          value: 1,
          done: true,
        }
      },
    }
  },
}

調用 Iterator 的經常使用場合

  • 解構賦值
let set = new Set().add('a').add('b').add('c')

let [x, y] = set
// x='a'; y='b'

let [first, ...rest] = set
// first='a'; rest=['b','c']
  • 擴展運算符
// 例一
var str = 'hello'
[...str] //  ['h','e','l','l','o']

// 例二
let arr = ['b', 'c']
['a', ...arr, 'd']
// ['a', 'b', 'c', 'd']
  • yield*
let generator = function* () {
  yield 1
  yield* [2, 3, 4]
  yield 5
}

var iterator = generator()

iterator.next() // { value: 1, done: false }
iterator.next() // { value: 2, done: false }
iterator.next() // { value: 3, done: false }
iterator.next() // { value: 4, done: false }
iterator.next() // { value: 5, done: false }
iterator.next() // { value: undefined, done: true }

瞭解遍歷器如何寫

遍歷器對象除了具備 next() 方法,還能夠具備 return() 方法和 throw() 方法。若是你本身寫遍歷器對象生成函數,那麼 next()方法是必須部署的, return() 方法和 throw() 方法是否部署是可選的。
/*
return()方法的使用場合是,若是for...of循環提早退出(一般是
由於出錯,或者有break語句),就會調用return()方法。若是一個對
象在完成遍歷前,須要清理或釋放資源,就能夠部署return()方法。
*/
function readLinesSync(file) {
  return {
    [Symbol.iterator]() {
      return {
        next() {
          return { done: false }
        },
        return() {
          file.close()
          return { done: true }
        },
      }
    },
  }
}

題目自測

一: for in 和 for of 的區別學習


二: 如下代碼會輸出什麼()this

const obj = { 2: 5, 3: 6, 4: 7 }
obj[Symbol.iterator] = function () {
  return {
    next: function () {
      if (this._countDown === 3) {
        return { value: this._countDown, done: true }
      }
      this._countDown = this._countDown + 1
      return { value: obj[this._countDown], done: false }
    },
    _countDown: 0,
  }
}
for (const i of obj) {
  console.log(i)
}
  • A. 2,3,4
  • B. 5,6,7
  • C. undefined,5,6
  • D. TypeError: obj is not iterable

題目解析

1、

Answer:

正確答案及解析:

for...in for...of
Applies to Enumerable Properties Iterable Collections
Use with Objects? Yes No
Use with Arrays? Yes, but not advised Yes
Use with Strings? Yes, but not advised Yes

2、

Answer:(C)

obj 是一個普通對象,正常遍歷會報錯如 D,但上面代碼中添加了 Symbol.iterator 屬性,因此能夠遍歷,遍歷時看 return 的值爲 obj[this._countDown] ,及把每次遍歷次數當作鍵名取值,能夠看獲得,obj 中只有 2,3,4 這三個鍵名的鍵,因此第一次取到的是 undefined,後面獲得 5 和 6 因此選 C

相關文章
相關標籤/搜索