迭代器模式:一個相對簡單的模式,目前絕大多數語言都內置了迭代器,以致於你們都不以爲這是一種設計模式javascript
迭代器模式指提供一種方法訪問一個聚合對象中的各個元素,而又不須要暴露該對象的內部表示
我的理解成遍歷聚合對象中的各個(某些)元素,並執行一個回調方法,現在大多數語言都已經內置了迭代器,但這裏記錄一下,理解其中的實現目的。html
$.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