博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js设计模式--迭代器模式
阅读量:6158 次
发布时间:2019-06-21

本文共 3589 字,大约阅读时间需要 11 分钟。

前言

本系列文章主要根据《JavaScript设计模式与开发实践》整理而来,其中会加入了一些自己的思考。希望对大家有所帮助。

文章系列

概念

迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。

场景

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 = '';      return $(str).appendTo($('body'));    } else {      var str = ''; // 表单上传      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 = '';    return $(str).appendTo($('body'));  };  return false;}var getFormUpladObj = function () {  var str = ' '; // 表单上传  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()复制代码

转载于:https://juejin.im/post/5c33155cf265da611f07db6b

你可能感兴趣的文章
浅析LUA中游戏脚本语言之魔兽世界
查看>>
飞翔的秘密
查看>>
Red Hat 安装源包出错 Package xxx.rpm is not signed
查看>>
编译安装mysql-5.6.16.tar.gz
查看>>
活在当下
查看>>
每天进步一点----- MediaPlayer
查看>>
PowerDesigner中CDM和PDM如何定义外键关系
查看>>
跨域-学习笔记
查看>>
the assignment of reading paper
查看>>
android apk 逆向中常用工具一览
查看>>
MyEclipse 报错 Errors running builder 'JavaScript Validator' on project......
查看>>
Skip List——跳表,一个高效的索引技术
查看>>
Yii2单元测试初探
查看>>
五、字典
查看>>
前端js之JavaScript
查看>>
Log4J日志配置详解
查看>>
实验7 BindService模拟通信
查看>>
scanf
查看>>
Socket编程注意接收缓冲区大小
查看>>
SpringMVC初写(五)拦截器
查看>>