JavaScript設(shè)計模式五(迭代器模式)

JavaScript設(shè)計模式五(迭代器模式)

迭代器模式的定義:

迭代器模式的意思就是提供一種方法能夠順序的訪問聚合對象中的各個元素,同時又不暴露該對象的內(nèi)部表示。大多數(shù)瀏覽器已經(jīng)支持了Array.prototype.forEach

由于兼容性問題宙拉,我們目前使用原生的forEach比較少延塑,我們先看看jQuery中的each方法

jQuery中的迭代器

jQuery中提供了each方法蠢护,來迭代聚合對象例如:

$.each([1,2,3], function(i, n) {
    console.log('下標:' + i);
    console.log('對應(yīng)的值:' + n);
});

如何自己實現(xiàn)一個迭代器

其實大家用到很多是for循環(huán)堤结,我們利用for循環(huán)就可以很快的實現(xiàn)一個迭代器


cons each = function(ary, callback) {
    for(let i = 0; i < ary.length; i++) {
        callback.call(null, i, ary[i]);
    }
}

each([1,2,3], function(i, n) {
    console.log('下標:' + i);
    console.log('對應(yīng)的值:' + n);
});

內(nèi)部迭代器與外部迭代器

迭代器根據(jù)不同的場景分為內(nèi)部迭代器和外部迭代器

內(nèi)部迭代器

上面的each函數(shù)就是屬于內(nèi)部迭代器,each函數(shù)的內(nèi)部定義好了規(guī)則肉拓,外部只需要一次調(diào)用吩案,不需要關(guān)心內(nèi)部迭代器是如何實現(xiàn)的。但是由于內(nèi)部迭代器的迭代規(guī)則被提前定義好了帝簇,each函數(shù)就沒法同時迭代連個數(shù)組了,例如我們需要判斷兩個數(shù)組是否相等靠益,這里就只能利用each的回調(diào)函數(shù)了丧肴。

var compare = function(array1, array2) {
    if (array1.length !== array2.length) {
        console.log('not equal');
        throw new Error();
    }
    
    each(array1, function(i, n) {
        if (array1[i] !== array2[i]) {
            console.log('not equal');
            throw new Error();
        }
    });
    
    console.log('equal');
}

compare([1,2,3], [1,2,3]);

但是其實這里其實雖然滿足了我們的需要,但是有一些缺點胧后,大家可以自己思考一下

在ES6中芋浮,新增了3中內(nèi)部迭代器,大家有興趣可以了解一下:entries()壳快、values()纸巷、keys()

外部迭代器

外部迭代器必須顯式的請求迭代下一個元素,我們先看一下ES6中的迭代器Iterator

迭代器Iterator的遍歷過程:

  • 創(chuàng)建一個指針對象眶痰,指向當前數(shù)據(jù)結(jié)構(gòu)的起始位置瘤旨,也就是說迭代器的本質(zhì)是一個指針對象
  • 第一次調(diào)用指針對象的next方法,可以將指針指向第一個數(shù)據(jù)成員
  • 第二次調(diào)用指針對象的next方法竖伯,可以將指針指向第二個數(shù)據(jù)成員
  • 不斷調(diào)用指針對象的next方法存哲,直到指向數(shù)據(jù)結(jié)構(gòu)的結(jié)束位置

在ES6中,一般迭代器和生成器一起使用

function *createIterator() {
    yield 1;
    yield 2;
    yield 3;
}

let iterator = createIterator();
iterator.next();
iterator.next();
iterator.next();

這里每當執(zhí)行一次yield時七婴,函數(shù)會停止執(zhí)行祟偷,直到再次調(diào)用迭代器的next方法。老生長談的問題打厘,我們看看ES5中如何實現(xiàn)類似的效果

function createIterator(items) {
    var i = 0;
    var done = (i >= items.length);
    var value = !done? items[i]: void 0;
    return {
        next: function() {
            done = (i >= items.length);
            value = !done? items[i++]: void 0;
            return {
                done: done,
                value: value,
            };
        },
        isDone: function() {
            return done;
        },
        getCurrItem: function(){
            return value;
        }
    }
}

var iterator = createIterator([1,2,3]);

iterator.next();
iterator.next();
iterator.next();
iterator.next();

那我們在回到上面的問題如何判斷兩個數(shù)組是否相等的問題修肠?

var compare = function(iterator1, iterator2) {
    while(!iterator1.isDone() && !iterator2.isDone()) {
        if (iterator1.getCurrItem() !== iterator2.getCurrItem()) {
            console.log('not equal');
        };
        iterator1.next();
        iterator2.next();
    }
    console.log('equal');
}

var iterator1 = createIterator([1,2,3]);
var iterator2 = createIterator([1,2,3]);
compare(iterator1, iterator2);

這兩種迭代器沒有優(yōu)劣之分,主要是根據(jù)場景來定

迭代類數(shù)組對象和字面量常量

不僅僅是數(shù)組可以被迭代户盯,對象嵌施、arguments這些有l(wèi)ength屬性,并且可以利用下標訪問的都可以被迭代莽鸭。在ES6中規(guī)定了可迭代的對象需要具備Symbol.iterator屬性艰管,具體可以參考阮一峰的ES6入門。一般來說我們對于數(shù)組采用的是for循環(huán)蒋川,對于字面量對象可以利用for in來迭代

迭代器模式應(yīng)用例子

例如我們需要做一個文件上傳的代碼牲芋,開始是這樣的:

var getUploadObj = function() {
    try {
        // IE的上傳組件
        return new ActiveXObject("TXFTNActiveX.FTNUpload")
    } catch (e){
        if (supportFlash()) {
            var str = '<object type="application/x-shockwave-flash"></object>';
            return $(str).appendTo($('body'));
        } else {
            var str = '<input name="file" type="file" />'
            return $(str).appendTo($('body'));
        }
    }
}

這段代碼本身沒啥問題,我們可能平常就是這么寫的,但是是否有優(yōu)化的空間呢缸浦?
這些try catch還有if else總是感覺不夠友好夕冲,而且如果我們增加了html5的上傳方式,我們又需要修改getUploadObj函數(shù)裂逐,這樣大家好像想到了方法歹鱼,把這3中上傳方式各自封裝成方法

var getActiveUploadObj = function(){
    try {
        // IE的上傳組件
        return new ActiveXObject("TXFTNActiveX.FTNUpload")
    } catch (e){
        return false;
    }
}

var getFlashUploadObj = function() {

    if (supportFlash()) {
        var str = '<object type="application/x-shockwave-flash"></object>';
       return $(str).appendTo($('body'));
    } 
    return false;   
}

var getFormUploadObj = function() {
    var str = '<input name="file" type="file" />'
    return $(str).appendTo($('body'));
}

var uploadObj = iteratorObj(getActiveUploadObj, getFlashUploadObj, getFormUploadObj);

function iteratorObj() {
    for(var i = 0; i < arguments.length; i++) {
        if (typeof arguments[i] === 'Function') {
            var uploadObj = arguments[i]();
            if (uploadObj !== false) {
                return uploadObj;
            }
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市卜高,隨后出現(xiàn)的幾起案子弥姻,更是在濱河造成了極大的恐慌,老刑警劉巖掺涛,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庭敦,死亡現(xiàn)場離奇詭異,居然都是意外死亡薪缆,警方通過查閱死者的電腦和手機秧廉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拣帽,“玉大人疼电,你說我怎么就攤上這事〖跏茫” “怎么了蔽豺?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拧粪。 經(jīng)常有香客問我茫虽,道長,這世上最難降的妖魔是什么既们? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任濒析,我火速辦了婚禮,結(jié)果婚禮上啥纸,老公的妹妹穿的比我還像新娘号杏。我一直安慰自己,他們只是感情好斯棒,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布盾致。 她就那樣靜靜地躺著,像睡著了一般荣暮。 火紅的嫁衣襯著肌膚如雪庭惜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天穗酥,我揣著相機與錄音护赊,去河邊找鬼惠遏。 笑死,一個胖子當著我的面吹牛骏啰,可吹牛的內(nèi)容都是我干的节吮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼判耕,長吁一口氣:“原來是場噩夢啊……” “哼透绩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起壁熄,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤帚豪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后草丧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體狸臣,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年方仿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片统翩。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡仙蚜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出厂汗,到底是詐尸還是另有隱情委粉,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布娶桦,位于F島的核電站贾节,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏衷畦。R本人自食惡果不足惜栗涂,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望祈争。 院中可真熱鬧斤程,春花似錦、人聲如沸菩混。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽沮峡。三九已至疚脐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間邢疙,已是汗流浹背棍弄。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工望薄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人照卦。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓式矫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親役耕。 傳聞我的和親對象是個殘疾皇子采转,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容