用vue.js學習es6(六):Iterator和for...of循環

一.Iterator (遍歷器)的概念:數組

  遍歷器(Iterator)就是這樣一種機制。它是一種接口,爲各類不一樣的數據結構提供統一的訪問機制。任何數據結構只數據結構

  要部署Iterator接口,就能夠完成遍歷操做(即依次處理該數據結構的全部成員)。函數

  Iterator的做用有三個:this

    一是爲各類數據結構,提供一個統一的、簡便的訪問接口;prototype

    二是使得數據結構的成員可以按某種次序排列;指針

    三是ES6創造了一種新的遍歷命令for...of循環,Iterator接口主要供for...of消費。code

  1.在ES6中,有三類數據結構原生具有Iterator接口:數組、某些相似數組的對象、Set和Map結構:對象

  let arr = ['a','b','c'];索引

  let it = arr[Symbol.iterator]();接口

  iter.next(); // {value:'a',done:false}

  iter.next(); // {value:'b',done:false}

  iter.next(); // {value:'c',done:false}

  iter.next(); // {value:undefined,done:true}

  2.對象(Object)之因此沒有默認部署Iterator接口,是由於對象的哪一個屬性先遍歷,哪一個屬性後遍歷是不肯定的,需

  要開發者手動指定。

  本質上,遍歷器是一種線性處理,對於任何非線性的數據結構,部署遍歷器接口,就等於部署一種線性轉換。

  不過,嚴格地說,對象部署遍歷器接口並非很必要,由於這時對象實際上被看成Map結構使用,ES5沒有Map結構,

  而ES6原生提供了。

  (1).一個對象若是要有可被for...of循環調用的Iterator接口,就必須在Symbol.iterator的屬性上部署遍歷器生成方

  法(原型鏈上的對象具備該方法也可)。  

  class RangeIterator {
    constructor(start, stop) {
      this.value = start;
      this.stop = stop;
    }

    [Symbol.iterator]() { return this; }

    next() {
      var value = this.value;
      if (value < this.stop) {
        this.value++;
        return {done: false, value: value};
      } else {
        return {done: true, value: undefined};
      }
    }
  }

  function range(start, stop) {
    return new RangeIterator(start, stop);
  }

  for (var value of range(0, 3)) {
    console.log(value); // 0 1 2
  }

  (2).代碼首先在構造函數的原型鏈上部署Symbol.iterator方法,調用該方法會返回遍歷器對象iterator,調用該對象

    的next方法,在返回一個值的同時,自動將內部指針移到下一個實例。

    function Obj(value) {
      this.value = value;
      this.next = null;
    }

    Obj.prototype[Symbol.iterator] = function() {
      var iterator = {
        next: mynext
      };

      var current = this;

      function mynext() {
        if (current) {
          var value = current.value;
          current = current.next;
          return {
            done: false,
            value: value
          };
        } else {
          return {
            done: true
          };
        }
      }
      return iterator;
    }

    var one = new Obj(1);
    var two = new Obj(2);
    var three = new Obj(3);

    one.next = two;
    two.next = three;

    for (var i of one){

      console.log(i); // 1 2 3
    }

  (3).相似數組的對象調用數組的Symbol.iterator方法的例子:

    let iterable = {
      0: 'a',
      1: 'b',
      2: 'c',
      length: 3,
      [Symbol.iterator]: Array.prototype[Symbol.iterator]
    };
    for (let item of iterable) {
      console.log(item); // 'a', 'b', 'c'
    }

  (4).普通對象部署數組的Symbol.iterator方法,並沒有效果:

    let iterable = {
      a: 'a',
      b: 'b',
      c: 'c',
      length: 3,
      [Symbol.iterator]: Array.prototype[Symbol.iterator]
    };
    for (let item of iterable) {
      console.log(item); // undefined, undefined, undefined
    }

二.for...of循環:

  一個數據結構只要部署了Symbol.iterator屬性,就被視爲具備iterator接口,就能夠用for...of循環遍歷它的成員。

  也就是說,for...of循環內部調用的是數據結構的Symbol.iterator方法。

  for...of循環可使用的範圍包括數組、Set 和 Map 結構、某些相似數組的對象(好比arguments對象、DOM NodeList 對象)、後文的   Generator對象,以及字符串。

  1.for...of循環能夠代替數組實例的forEach方法:

  const arr = ['red', 'green', 'blue'];

  arr.forEach(function (element, index) {
    console.log(element); // red green blue
    console.log(index); // 0 1 2
  });

  for(let i of arr){

    console.log(i); //  red green blue

  }

  2.JavaScript原有的for...in循環,只能得到對象的鍵名,不能直接獲取鍵值。ES6提供for...of循環,容許遍歷得到

  鍵值:

  var arr = ['a','b','c','d'];

  for(let a in arr){

    console.log(a); // 0 1 2 3

  }

  for(let a of arr){

    console.log(a); // a b c d

  }

  3.for...of循環調用遍歷器接口,數組的遍歷器接口只返回具備數字索引的屬性。這一點跟for...in循環也不同:

  let arr = [3,5,7];

  arr.hello = 'hello';

  for(let i in arr){

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

  }

  for(let i of arr){

     console.log(i); // "3","5","7"

  }

相關文章
相關標籤/搜索