js设想形式--迭代器形式

媒介

本系列文章重要依据《JavaScript设想形式与开辟实践》整顿而来,个中会加入了一些本身的思索。愿望对人人有所协助。

文章系列

js设想形式–单例形式

js设想形式–战略形式

js设想形式–代办形式

观点

迭代器形式是指供应一种要领递次接见一个聚合对象中的各个元素,而又不需要暴露该对象的内部示意。迭代器形式能够把迭代的历程从营业逻辑中分离出来,在运用迭代器形式以后,纵然不体贴对象的内部组织,也能够按递次接见个中的每一个元素。

UML类图

《js设想形式--迭代器形式》

场景

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()
    原文作者:aoping
    原文地址: https://segmentfault.com/a/1190000017752756
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞