es6之Iterator和for...of循環

什麼是Iterator(遍歷器)

Iterator是一種機制,一種接口,爲各類不一樣的數據結構提供統一的訪問機制。任何數據結構,只要部署Iterator接口,就能夠完成遍歷操做。遍歷實際上是一種線性處理,有序的。數組

Iterator遍歷的過程:bash

  • 一、建立一個遍歷指針,指向當前數據結構的起始位置
  • 二、第一次調用指針對象的next方法,返回第一個成員
  • 三、第二次調用next方法,返回第二個成員
  • 四、不斷的調用next方法,直到指針對象指向數據結構的結束位置
//獲取遍歷器
var arr = [1,2][Symbol.iterator]();

arr.next(); //{value: 1, done: false}
arr.next(); //{value: 2, done: false}
arr.next(); //{value: undefined, done: true}
arr.next(); //{value: undefined, done: true}
複製代碼

返回的成員信息是一個對象,包含{value: any, done: boolean}。調用指針對象的next方法就能夠遍歷事先給定的數據結構。數據結構

因爲Iterator只是把接口規範加到數據結構上,因此遍歷器和所遍歷的數據結構是分開的。函數

什麼是遍歷器生成函數

默認的Iterator接口部署在數據結構的Symbol.iterator屬性上,屬性對應的值就是遍歷器生成函數,因此只要具備Symbol.iterator屬性就能夠遍歷。若是Symbol.iterator方法反應的不是遍歷器對象生成函數,就好報錯。ui

執行Symbol.iterator屬性就會返回一個遍歷器對象。該對象的根本特徵就是具備next方法,每次調用next就會返回一個表明當前成員的信息對象,具備value和done兩個屬性。spa

const obj = {
    a: 'aa',
    [Symbol.iterator]: function(){
        return {
            next(){
                return {
                    value: 1,
                    done: true,
                }
            }
        }
    }
}
var objIterator = obj[Symbol.iterator]();
objIterator.next(); //{value: 1, done: true}
objIterator.next(); //{value: 1, done: true}
複製代碼

當使用for...of循環遍歷某種數據結構時,就會自動去尋找Iterator接口設計

//無限循環,謹慎執行
for(let value of obj){
    console.log(value); //1
}
複製代碼

原生具有Iterator接口的數據結構:指針

  • Array
  • Set
  • Map
  • String
  • TypeArray
  • 函數的argument對象
  • NodeList對象
  • Generator對象

對象(Object)沒有Iterator接口,由於對象屬性遍歷前後順序是不肯定的。code

Iterator接口與Generator函數

Symbol.iterator最簡單的實現方式對象

var myIterator = {};
myIterator[Symbol.iterator] = function*(){
    yield 1;
    yield* [2, 3];
    yield 4;
}

[...myIterator] //[1,2,3,4]
複製代碼

for...of循環與for..in循環的區別

一個數據結構只要部署了Symbol.iterator數據,就被視爲具備Iterator接口,就可使用for...of循環它的成員。

for...of循環調用接口,數組的遍歷接口只返回具備數字索引的屬性。

var arr = [1,2];
a[3] = 3; 
arr.a = 'aa';

for(let value of arr){
    console.log(value);
}
// 1 2 empty 3

for(let value in arr){
    console.log(value);
}
// '0' '1' '3' 'aa'
複製代碼

for...in循環遍歷缺點:

  • 只能得到對象的鍵名,不能直接獲取鍵值
  • 不只遍歷數字鍵名,遍歷手動添加的其餘鍵名,甚至包括原型鏈上的鍵
  • 某些狀況下以任意順序遍歷鍵名

for...in循環主要爲遍歷對象而設計的,不適用於遍歷數組

for...of循環遍歷優勢:

  • 不一樣於forEach方法,它能夠與break、continue、return配合使用
  • 提供了遍歷全部數據結構的統一接口
  • 對於字符串,能夠識別32位UTF-16字符

for...of會把數組中空值也給遍歷處理

對象的遍歷,最好採用Object.keys + for...of

var obj = {
    a: 'aa',
    b: 'bb'
};

for(let key of Object.keys(obj)){
    console.log(key, obj[key])
}
//'a' 'aa'
//'b' 'bb'
複製代碼
相關文章
相關標籤/搜索