1. 程式人生 > 其它 >Iterator遍歷器

Iterator遍歷器

Iterator(遍歷器)的概念

JavaScript原有的表示“集合”的資料結構,主要是陣列(Array)和物件(Object),ES6又添加了Map和Set。這樣就有了四種資料集合,使用者還可以組合使用它們,定義自己的資料結構,比如陣列的成員是Map,Map的成員是物件。這樣就需要一種統一的介面機制,來處理所有不同的資料結構。

遍歷器(Iterator)就是這樣一種機制。它是一種介面,為各種不同的資料結構提供統一的訪問機制。任何資料結構只要部署Iterator介面,就可以完成遍歷操作(即依次處理該資料結構的所有成員)。

Iterator的作用有三個:一是為各種資料結構,提供一個統一的、簡便的訪問介面;二是使得資料結構的成員能夠按某種次序排列;三是ES6創造了一種新的遍歷命令for...of

迴圈,Iterator介面主要供for...of消費。

Iterator的遍歷過程是這樣的。

(1)建立一個指標物件,指向當前資料結構的起始位置。也就是說,遍歷器物件本質上,就是一個指標物件。

(2)第一次呼叫指標物件的next方法,可以將指標指向資料結構的第一個成員。

(3)第二次呼叫指標物件的next方法,指標就指向資料結構的第二個成員。

(4)不斷呼叫指標物件的next方法,直到它指向資料結構的結束位置。

每一次呼叫next方法,都會返回資料結構的當前成員的資訊。具體來說,就是返回一個包含valuedone兩個屬性的物件。其中,value屬性是當前成員的值,done屬性是一個布林值,表示遍歷是否結束。

我們應該如何理解這種遍歷器的機制?我們可以聯想到自己的生活,比如我們的冰箱、洗衣機、電視雖然功能各自不同,但是有一個“介面”是統一的,那就是電源線, 不是兩頭的就是三頭的

iterator是一種介面機制,使用或者設計的時候必須要遵循這種機制

Iterator的模擬封裝

function makeIterator(array) {
    // 起始下標
    var nextIndex = 0;
    return {
      // 封裝的next方法
      next: function() {
        return nextIndex < array.length ?
          {value: array[nextIndex
++], done: false} : {value: undefined, done: true}; } }; } // 註冊iterator var it = makeIterator(['1', '2','3']); console.log(it.next()); console.log(it.next()); console.log(it.next()); console.log(it.next());

上圖中的{value:**,done:false}這種格式的返回就是所謂的iterator介面的規則,value表示當前這次遍歷出來的值,done表示遍歷是否結束。false為未結束,true為已結束

Iterator的遍歷過程是這樣的:

1>建立一個指標物件,指向當前資料結構的起始位置。也就是說,遍歷器物件本質上,就是一個指標物件。

2>第一次呼叫指標物件的next方法,可以將指標指向資料結構的第一個成員。

3>第二次呼叫指標物件的next方法,指標就指向資料結構的第二個成員。

4>不斷呼叫指標物件的next方法,直到它指向資料結構的結束位置。

資料結構的預設Iterator介面

Iterator介面的目的,就是為所有資料結構,提供了一種統一的訪問機制,即for...of迴圈。當使用for...of迴圈遍歷某種資料結構時,該迴圈會自動去尋找Iterator介面。

一種資料結構只要部署了Iterator介面,我們就稱這種資料結構是”可遍歷的“(iterable)。

ES6規定,預設的Iterator介面部署在資料結構的Symbol.iterator屬性,或者說,一個數據結構只要具有Symbol.iterator屬性,就可以認為是“可遍歷的”(iterable)

比如陣列就是擁有遍歷器能力的

如何使用遍歷器?

以陣列為例

<script>
      var arr = [1,2,3,4,5];
        // 註冊iterator
        var it = arr[Symbol.iterator]();
        console.log(it.next());
        console.log(it.next());
        console.log(it.next());
        console.log(it.next());
        console.log(it.next());
        console.log(it.next());
   </script>

在ES6中,有三類資料結構原生具備Iterator介面:陣列、某些類似陣列的物件、String、Set和Map結構

for...of迴圈

一個數據結構只要部署了Symbol.iterator屬性,就被視為具有iterator介面,就可以用for...of迴圈遍歷它的成員

比如陣列

<script>
    var arr = [1,2,3,4,5];
    for(let item of arr){
      console.log(item);
    }
   </script>

arguments物件

<script>
    function arr() {
      for (let x of arguments) {
        console.log(x);
      }
    }
    arr(1,2,3,4,5);
   </script>

除了for...of迴圈以外,擴充套件運算子(...)、解構賦值和Array.from方法內部呼叫的,都是遍歷器介面