js设计模式总结-迭代器模式
2024-10-12 02:58:09
迭代器模式
要解决的问题
迭代器要解决的问题很简单很单纯,就是进行遍历操作。
实现原理
基本所有语言都实现了迭代器,javascript也不例外,如Array.prototype.forEach
,for..of..
,for..in..
,for
迭代器的种类分两种,内部迭代器,外部迭代器。
内部迭代器
内部迭代器的迭代过程对外部是不可控的,内部自己实现迭代过程.比如forEach
, jQuery中的$.each
外部迭代器
外部迭代器就相对灵活,可以控制迭代过程,需要显式调用迭代操作.外部迭代器较内部迭代器来说更方便扩展。
外部迭代器的一个实现
// itObj 是被迭代对象,需要包含length属性
var Iterator = function(itObj) {
this.obj = itObj
this.currentItem = 0
this.length = itObj.length
}
Iterator.prototype.next = function() {
if (this.currentItem < this.length) {
this.currentItem++
}
}
Iterator.prototype.getCurrentItem = function() {
return this.obj[this.currentItem]
}
Iterator.prototype.isDone = function() {
return this.currentItem >= this.length
}
var it = new Iterator([1, 2, 3])
console.log(it.getCurrentItem()) // 1
it.next()
console.log(it.getCurrentItem()) // 2
it.next()
console.log(it.getCurrentItem()) // 3
it.next()
console.log(it.getCurrentItem()) // 3
扩展我们的迭代器,实现两个数组的merge函数
//两个迭代器
var it1 = new Iterator([1,3,4,6])
var it2 = new Iterator([2,3,5,7])
var merge = function(it1, it2) {
var tmp = []
// 两个迭代器同时遍历
while(!it1.isDone() && !it2.isDone()) {
if (it1.getCurrentItem() > it2.getCurrentItem()) {
tmp.push(it2.getCurrentItem())
it2.next()
} else if (it1.getCurrentItem() < it2.getCurrentItem()) {
tmp.push(it1.getCurrentItem())
it1.next()
} else {
tmp.push(it1.getCurrentItem())
it1.next()
it2.next()
}
}
// 如果it1没被遍历完,直接push
while(!it1.isDone()) {
tmp.push(it1.getCurrentItem())
it1.next()
}
// 如果it2没被遍历完,直接push
while(!it2.isDone()) {
tmp.push(it2.getCurrentItem())
it2.next()
}
return tmp
}
console.log(merge(it1, it2)) // [1, 2, 3, 4, 5, 6, 7]
可以看到用外部迭代器很容易地控制迭代过程,扩展功能
实践中的应用
一个copy自书上的例子
获取上传对象
未使用迭代器的版本
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'));
}
}
}
我们看到其中夹杂着try...catch
语句和大量的if
语句,严重违反了开闭原则。
使用迭代器重构
var getActiveUploadObj = function() {
try {
return new ActiveXObject("TXFTNActiveX.FTNUpload"); //IE上传控件
} 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" 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, getFormUploadObj)
重构代码之后,我们可以看到,获取不同上传对象的方法被隔离在各自的函数里互不干扰, try、catch 和 if 分支不再纠缠在一起,使得我们可以很方便地的维护和扩展代码。
最新文章
- UI第十七节——UIScrollView
- sqlserver 还原数据库
- 关于ThreadLocal
- Apache Spark GraphX的简介
- Android编译输出 资源指定AAPT
- Base64图片与UIImage的相互转化
- 搭建互联网DNS构架
- javascript 中的apply()和call()方法详解
- MUI在项目中使用时遇到的问题的个人分享
- RabbitMQ管理界面
- JDK8源码之Arrays
- InstallShield:卸载时文字叠加,文字乱码
- 无损压缩PNG工具
- Javascript函数心得
- 峰Spring4学习(2)依赖注入的几种方式
- Excellent JD
- 在android中画圆形图片的几种办法
- Learning PHP Design Patterns
- TOJ 1721 Partial Sums
- ife task0003学习笔记(四):JavaScript构造函数
热门文章
- 安装eclipse的hadoop开发环境--2
- android switch语句报错:case expressions must be constant expressions
- Array.prototype.slice.call(arguments)
- JAVA用途
- [Android] ListView关于adapter多种view设置
- docker命令小记
- Office2010安装错误1402问题(我安装成功了)
- Classic Shell 4.2.4 中文版已经发布
- SQL 递归
- 用Swift语言做App开发之单元测试