资讯专栏INFORMATION COLUMN

js设计模式--迭代器模式

binta / 1061人阅读

摘要:文章系列设计模式单例模式设计模式策略模式设计模式代理模式概念迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

前言

本系列文章主要根据《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 = "";
      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://www.ucloud.cn/yun/100673.html

相关文章

  • JS迭代模式《JavaScript设计模式与开发实践》阅读笔记

    摘要:但实际中,内部迭代器和外部迭代器两者并无优劣。迭代器并不只迭代数组迭代器模式不仅能迭代数组,还可以迭代一些类数组对象。晚安了,参考设计模式与开发实践曾探本文作者本文链接迭代器模式设计模式与开发实践阅读笔记 迭代器模式:一个相对简单的模式,目前绝大多数语言都内置了迭代器,以至于大家都不觉得这是一种设计模式 迭代器模式 迭代器模式指提供一种方法访问一个聚合对象中的各个元素,而又不需要暴露该...

    djfml 评论0 收藏0
  • 从观察者模式迭代模式系统讲解 RxJS Observable(一)

    摘要:是的缩写,起源于,是一个基于可观测数据流结合观察者模式和迭代器模式的一种异步编程的应用库。是基于观察者模式和迭代器模式以函数式编程思维来实现的。学习之前我们需要先了解观察者模式和迭代器模式,还要对流的概念有所认识。 RxJS 是 Reactive Extensions for JavaScript 的缩写,起源于 Reactive Extensions,是一个基于可观测数据流 Stre...

    notebin 评论0 收藏0
  • ES6 Features系列:GeneratorFunction介绍

    摘要:没有显示显示显示关键字迭代器生成器用于马上退出代码块并保留现场,当执行迭代器的函数时,则能从退出点恢复现场并继续执行下去。迭代器迭代器是一个拥有方法和方法的对象,通过函数不断执行以关键字分割的代码段,通过函数令分割的代码段抛出异常。 一、前言                            第一次看koajs的示例时,发现该语句 function *(next){..........

    golden_hamster 评论0 收藏0
  • javascript中的设计模式(一)

    摘要:模式迭代器模式顾名思义,迭代器可以将对于一个聚合对象内部元素的访问与业务逻辑分离开。模式组合模式组合模式将对象组合成树形结构,以表示层级结构。重点是,叶结点与中间结点有统一借口。本文总结自设计模式与开发实践,曾探著 模式1 - 单例模式 单例模式的核心是确保只有一个实例,并且提供全局访问。 特点: 满足单一职责原则 : 使用代理模式,不在构造函数中判断是否已经创建过该单例; 满足惰...

    chaosx110 评论0 收藏0
  • [译] ES6 学习笔记:关于 ES2015 特性的详细概述

    摘要:将转换成常见的使用实现的基于迭代器的迭代。处停止迭代器基于鸭子模型接口这里使用语法仅仅为了说明问题使用支持为了使用迭代器属性需要引入。生成器是迭代器的子类,包含了附加的与。 原文地址:http://babeljs.io/docs/learn-...本文基于Luke Hoban精妙的文章《es6features》,请把star献给他,你可以在此尝试这些特性REPL。 概述 ECMAScr...

    leoperfect 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<