JS迭代器模式《JavaScript設計模式與開發實踐》閱讀筆記

迭代器模式:一個相對簡單的模式,目前絕大多數語言都內置了迭代器,以致於你們都不以爲這是一種設計模式javascript

迭代器模式

迭代器模式指提供一種方法訪問一個聚合對象中的各個元素,而又不須要暴露該對象的內部表示

我的理解成遍歷聚合對象中的各個(某些)元素,並執行一個回調方法,現在大多數語言都已經內置了迭代器,但這裏記錄一下,理解其中的實現目的。html

jQuery 中的$.each

$.each([1,2,3,4,5], function(i, el) {
    console.log('index: ',i)
    console.log('item: ', el)
})

如何自定義一個each函數,實現以上的效果呢?java

var each = function (arr, callback) {
    for (var i = 0, len = arr.length; i<len; i++) {
        callback.call(arr[i], i, arr[i])
    }
}

each([1,2,3,4,5], function(i, el) {
    console.log('index: ',i)
    console.log('item: ', el)
})

這裏實現了一個較爲簡單的內部迭代器方法,然而迭代器同時還有一種相似——外部迭代器設計模式

內部迭代器和外部迭代器

內部迭代器

如剛剛自定義個each方法,這種迭代器在內部已經定義好了迭代規則,如,迭代的方向,迭代是否在知足條件是停止。數組

內部迭代器在調用時很是方便,外界不用去關心其內部的實現。在每一次調用時,迭代器的規則就已經制定,若是遇到一些不一樣樣的迭代規則,此時的內部迭代器並不很優雅ide

like this:函數

// 當須要同時迭代兩個數組時

var compare = function(ary1, ary2) {
    if (ary1.length !== ary2.length) {
        throw new Error ('ary1 和 ary2 不相等')
    }
    
    each(ary1, function(i, n){
        if (n !== ary2[i]) {
            throw new Error ('ary1 和 ary2 不相等')
        }
    })
    alert ('ary1, ary2相等')
}

compare([1,2,3,4], [2,3,4,5,6])

但若是用外部迭代器來實現一個這樣的需求時,就顯得更加清晰易懂ui

外部迭代器

外部迭代器必須顯示地請求迭代下一個元素(ltertor.next())this

外部迭代器雖然增長了調用的複雜度,但加強了迭代器的靈活性,咱們能夠手工控制迭代過程或者順序。Generators 應該就是一種外部迭代器的實現。那麼接下來看看如何本身實現一個外部迭代器:設計

var Iterator = function(obj) {
    var current = 0
    var next = function() {
        current += 1
    }
    var isDone = function() {
        return current >= obj.lenght
    }
    var getCurrent = function() {
        return obj[current]
    }
    return {
        next: next,
        length: obj.length,
        isDone:isDone,
        getCurrent:getCurrent
    }
}

經過這個迭代器,咱們就能夠更加優雅的實現剛剛的compare方法來迭代兩個數組了:

var compare = function(iteraotr1, iteraotr2) {
    if (iteraotr1.length !== iteraotr2.length) {
        alert('不相等')
    }
    //外部設定條件來決定迭代器的進行
    while (!iteraotr1.isDone() && !iteraotr2.isDone()) {
        if (iteraotr1.getCurrent() !== iteraotr2.getCurrent()) {
            alert('不相等')
        }
        iteraotr1.next()
        iteraotr2.next()
    }
    alert('相等')
}

var iteraotr1 = Iterator([1,2,3])
var iteraotr2 = Iterator([1,2,3])

compare(iteraotr1,iteraotr2) // 相等

經過外部迭代器,較爲優雅的實現了這個同時迭代兩個數組的需求。但實際中,內部迭代器和外部迭代器二者並沒有優劣。具體使用何種,需更具實際狀況來決定。

迭代器並不僅迭代數組

迭代器模式不只能迭代數組,還能夠迭代一些類數組對象。好比arguments{a:1,n:2,c:3}等。其須具有的就是對象擁有一個length屬性能夠訪問,並能經過下標來訪問對象中的各個元素。

其中for ... of 能夠來循環數組,對象字面量則能夠經過for ... in來訪問其中的各個屬性的值來達到目的。

迭代器能夠停止

在for循環中,咱們能夠經過break來跳出循環,因此在迭代器模式中。咱們能夠利用這個來提早終止迭代。接下來咱們改在一下最開始的each函數

var each = function(arr, callback) {
    var result
    for (var i = 0, len = arr.length; i < len; i++) {
        result = callback.call(arr[i], i, arr[i])
        if (result === false) {
            break
        }
    }
}

each([1,2,3,4,5,6,7], function(i, el) {
    if (el > 3) {
        return false
    }
    console.log(el)
})

最後

迭代器模式的實現原理較爲簡單,JavaScript中有更多針對不一樣需求的迭代器實現。咱們也能夠本身定義一個適合的規則來處理數組,類數組這樣的對象。但每每最多見的也是最容易被忽視的,而一個常見的東西每每是更好用更受用的。

晚安了,skr skr skr

參考

《JavaScript設計模式與開發實踐》—— 曾探

本文做者: Roy Luo

本文連接: JS迭代器模式《JavaScript設計模式與開發實踐》閱讀筆記

相關文章
相關標籤/搜索