前言本系列文章主要根据《JavaScript设计模式与开发实践》整理而来,其中会加入了一些自己的思考。希望对大家有所帮助。文章系列js设计模式–单例模式js设计模式–策略模式js设计模式–代理模式概念迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。UML类图场景JavaScript已经内置迭代器,如forEach Iterator等,再如jquery的$.each分类内部迭代器定义内部已经定义好了迭代规则,它完全接手整个迭代过程,外部只需要一次初始调用实现var each = function (ary, callback) { for (var i = 0; i < ary.length; i++) { callback(i, ary[i]) }}each([1, 2, 3, 4, 5], function (i, item) { console.log(i, item)})优缺点优点:内部迭代器在调用的时候非常方便,外界不用关心迭代器内部的实现,跟迭代器的交互也仅 仅是一次初始调用缺点:由于内部迭代器的迭代规则已经被提前规 定,上面的 each 函数就无法同时迭代2个数组,如下代码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 ], [ 1, 2, 4 ] ); // throw new Error ( ‘ary1 和ary2 不相等’ );外部迭代器定义外部迭代器必须显式地请求迭代下一个元素实现我们模拟一个es6迭代器var Iterator = function (ary) { this.ary = ary this.index = 0}Iterator.prototype.isDone = function () { return this.index >= this.ary.length}Iterator.prototype.next = function () { if (!this.isDone()) { var res = this.ary[this.index] this.index++ return { value: res, done: this.isDone() } }}var a = new Iterator([1, 2, 3])while (!a.isDone()) { console.log(a.next())}下面解决一下上面那个问题var a = new Iterator([1, 2, 3, 3])var b = new Iterator([1, 2, 3])function compare(iterator1, iterator2) { while (!iterator1.isDone() || !iterator2.isDone()) { if (iterator1.next().value !== iterator2.next().value) { return false } } return true}compare(a, b)例子文件上传实现文件上传对象var getUploadObj = function () { try { return new ActiveXObject(“TXFTNActiveX.FTNUpload”); } catch (e) { // IE 上传控件 if (supportFlash()) { // 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’)); } }};缺点:第一是很难阅读,第二是严重违反开闭原则改进var getActiveUploadObj = function () { try { return new ActiveXObject(“TXFTNActiveX.FTNUpload”); } catch (e) { return false; }};var getFlashUploadObj = function () { if (supportFlash()) { // supportFlash 函数未提供 var str = ‘<object type=“application/x-shockwave-flash”></object>’; return $(str).appendTo($(‘body’)); }; return false;}var getFormUpladObj = function () { var str = ‘<input name=“file” type = “file” class = “ui-file” / > ‘; // 表单上传 return $(str).appendTo($(‘body’));}var iteratorUploadObj = function () { for (var i = 0, fn; fn = arguments[i++];) { var uploadObj = fn(); if (uploadObj !== false) { return uploadObj; } };}var uploadObj = iteratorUploadObj(getActiveUploadObj, getFlashUploadObj, getFormUpladObj);es6基于类实现class Iterator { constructor(conatiner) { this.list = conatiner.list this.index = 0 } next() { if (this.hasNext()) { return this.list[this.index++] } return null } hasNext() { if (this.index >= this.list.length) { return false } return true }}class Container { constructor(list) { this.list = list } getIterator() { return new Iterator(this) }}// 测试代码let container = new Container([1, 2, 3, 4, 5])let iterator = container.getIterator()while(iterator.hasNext()) { console.log(iterator.next())}es6中的Iterator我们都知道Array、Map、Set、类对象(如arguments NodeList等)都有一个Symbol.iterator迭代方法,可以通过以下方式取得var a = [1,2,3]console.log(a[Symbol.iterator])另外generator也会返回迭代器function* gen() { yield 1 yield ‘1’}var a = gen()a.next()