学习JavaScript设计模式之迭代器模式


Posted in Javascript onJanuary 19, 2016
  • 迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

JavaScript中的Array.prototype.forEach

一、jQuery中的迭代器

$.each([1, 2, 3], function(i, n) {
  console.log("当前下标为:"+ i + " 当前元素为:"+ n );
});

二、实现自己的迭代器

var each = function(ary, callback) {
  for(var i = 0, l = ary.length; i < l; i++) {
    callback.call(ary[i], i, ary[i]);
  }  
};
each([1, 2, 3], function(i, n) {
  console.log("当前下标为:"+ i + " 当前元素为:"+ n );
});

注意:区别于Array.prototype.forEach的参数!!!

[1, 2, 3].forEach(function(n, i, curAry){
  console.log("当前下标为:"+ i + " 当前元素为:"+ n + " 当前数组为:" + curAry);
})

三、内部迭代器、外部迭代器

(1)内部迭代器:已经定义好了迭代规则,它完全接手整个迭代过程,外部只需一次初始调用。上述自定义each即为内部迭代器!
(2)外部迭代器:必须显示地请求迭代下一个元素。
示例:判断两个数组是否相等

示例一:内部迭代器

// 内部迭代器
var each = function(ary, callback) {
  for(var i = 0, l = ary.length; i < l; i++) {
    callback.call(ary[i], i, ary[i]);
  }  
};
// 比较函数
var compareAry = function(ary1, ary2) {
  if(ary1.length != ary2.length) {
    throw new Error("不相等"); // return console.log("不相等"); 
  }
  // 且住
  each(ary1, function(i, n) {
    if(n !== ary2[i]) {
      // return console.log("不相等"); 
      // return 只能返回到each方法外,后续console.log("相等")会继续执行,所以这里得使用throw
      throw new Error("不相等");
    }
  });
  console.log("相等");
}

compareAry([1, 2, 3], [1, 2, 4]);

示例二:外部迭代器

// 外部迭代器
var Iterator = function(obj) {
  var current = 0,
    next = function() {
      current++;
    },
    isDone = function() {
      return current >= obj.length;  
    },
    getCurrentItem = function() {
      return obj[current];
    };
  return {
    next: next,
    isDone: isDone,
    getCurrentItem: getCurrentItem
  };
};
// 比较函数
var compareAry = function(iterator1, iterator2) {
  while( !iterator1.isDone() && !iterator2.isDone() ){
    if(iterator1.getCurrentItem() !== iterator2.getCurrentItem()) {
      throw new Error("不相等");
    }
    iterator1.next();
    iterator2.next();
  }
  console.log("相等");
}

compareAry(new Iterator([1, 2, 3]), new Iterator([1, 2, 4]));

四、终止迭代器

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

each([1, 2, 4, 1], function(i, n) {
  if(n > 3) {
    return false;
  }
  console.log(n);
});

五、应用(落地)

文件上传,根据不同的浏览器获取相应的上传组件对象。
对比《JavaScript设计模式?责任链模式》

var iteratorUploadObj = function() {
  for(var i = 0, fn; fn = arguments[i]; i++) {
    var uploadObj = fn();
    if(uploadObj !== false) {
      return uploadObj;
    }
  }
};

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

function getActiveUploadObj() {
  try{
    return new ActiveObject("TXFTNActiveX.FTNUpload"); // IE上传控件
  }catch(e) {
    return false;
  }
}

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

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

// 是否支持flash
function supportFlash() {
  var hasFlash = 0; //是否安装了flash
  var flashVersion = 0; //flash版本
  if (document.all) {
    var swf = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
    if (swf) {
      hasFlash = 1;
      VSwf = swf.GetVariable("$version");
      flashVersion = parseInt(VSwf.split(" ")[1].split(",")[0]);
    }
  } else {
    if (navigator.plugins && navigator.plugins.length > 0) {
    var swf = navigator.plugins["Shockwave Flash"];
      if (swf) {
        hasFlash = 1;
        var words = swf.description.split(" ");
        for (var i = 0; i < words.length; ++i) {
          if (isNaN(parseInt(words[i]))) continue;
          flashVersion = parseInt(words[i]);
        }
      }
    }
  }
  return { f: hasFlash, v: flashVersion };
}

希望本文所述对大家学习javascript程序设计有所帮助。

Javascript 相关文章推荐
jQuery动态添加的元素绑定事件处理函数代码
Aug 02 Javascript
JQuery动画animate的stop方法使用详解
May 09 Javascript
与Math.pow 相反的函数使用介绍
Aug 04 Javascript
Vue.js中数组变动的检测详解
Oct 12 Javascript
VUE axios发送跨域请求需要注意的问题
Jul 06 Javascript
JavaScript截屏功能的实现代码
Jul 28 Javascript
浅谈Angular4中常用管道
Sep 27 Javascript
webpack优化的深入理解
Dec 10 Javascript
vuex 解决报错this.$store.commit is not a function的方法
Dec 17 Javascript
jQuery三组基本动画与自定义动画操作实例总结
May 09 jQuery
Vue js with语句原理及用法解析
Sep 03 Javascript
React-vscode使用jsx语法的问题及解决方法
Jun 21 Javascript
学习JavaScript设计模式之观察者模式
Apr 22 #Javascript
JS获取CSS样式(style/getComputedStyle/currentStyle)
Jan 19 #Javascript
详解javascript实现自定义事件
Jan 19 #Javascript
JS拖拽组件学习使用
Jan 19 #Javascript
理解JS绑定事件
Jan 19 #Javascript
AngularJS模块学习之Anchor Scroll
Jan 19 #Javascript
jQuery unbind()方法实例详解
Jan 19 #Javascript
You might like
《PHP编程最快明白》第八讲:php启发和小结
2010/11/01 PHP
PHP获取mysql数据表的字段名称和详细信息的方法
2014/09/27 PHP
JS Array对象入门分析
2008/10/30 Javascript
js数组去重的常用方法总结
2014/01/24 Javascript
javascript针对不确定函数的执行方法
2015/12/16 Javascript
JavaScript里 ==与===区别详解
2016/08/16 Javascript
从0开始学Vue
2016/10/27 Javascript
AngularJS入门教程之Helloworld示例
2016/12/25 Javascript
Javascript中数组去重与拍平的方法示例
2017/02/03 Javascript
javascript 跨域问题以及解决办法
2017/07/17 Javascript
Vue 表单控件绑定的实现示例
2017/08/11 Javascript
利用JS判断客户端类型你应该知道的四种方法
2017/12/22 Javascript
webpack打包node.js后端项目的方法
2018/03/10 Javascript
nuxt框架中路由鉴权之Koa和Session的用法
2018/05/09 Javascript
js删除数组中某几项的方法总结
2019/01/16 Javascript
页面内锚点定位及跳转方法总结(推荐)
2019/04/24 Javascript
Vue 幸运大转盘实现思路详解
2019/05/06 Javascript
微信小程序select下拉框实现效果
2019/05/15 Javascript
vue添加自定义右键菜单的完整实例
2020/12/08 Vue.js
[02:03]永远的信仰DOTA2 中国军团历届国际邀请赛回顾
2016/06/26 DOTA
Python对象类型及其运算方法(详解)
2017/07/05 Python
Python+tkinter使用80行代码实现一个计算器实例
2018/01/16 Python
Django压缩静态文件的实现方法详析
2018/08/26 Python
pandas取出重复数据的方法
2019/07/04 Python
Python socket非阻塞模块应用示例
2019/09/12 Python
Python基于yield遍历多个可迭代对象
2020/03/12 Python
python 利用zmail库发送邮件
2020/09/11 Python
灵活运用CSS3特性绘制简易版围棋效果
2016/09/28 HTML / CSS
美体小铺加拿大官方网站:The Body Shop加拿大
2016/10/30 全球购物
加拿大城市本地限时优惠:Buytopia.ca
2018/09/19 全球购物
国际花店:Pickup Flowers
2020/04/10 全球购物
国贸专业的职业规划范文
2014/01/23 职场文书
《月光启蒙》教学反思
2014/03/01 职场文书
刘公岛导游词
2015/02/05 职场文书
element多个表单校验的实现
2021/05/27 Javascript
Java实现注册登录跳转
2022/06/16 Java/Android