JS设计模式之迭代器模式

迭代器模式(Iterator)

在不暴露对象内部结构的同时,可以顺序地访问聚合对象内部的元素

迭代器模式

(一个幻灯片的基类案例)

'use strict';

// 背景:页面中有好多焦点图,每一种都要重写一遍元素循环,所以需要建立一个基类,然后让不同种类的焦点图(轮播,淡入淡出)继承基类,此外,迭代器模式比较适合解决重复循环迭代的问题


// 迭代器
var Iterator = function(items, container) {
  var container = container && document.getElementById(container) || document;
  var items = container.getElementsByTagName(items);

  var length = items.length;

  // 当前索引
  var index = 0;

  var splice = Array.prototype.splice;

  return {
    /*
     * 获取第一个元素
     */
    first: function() {
      index = 0;
      return items[index];
    },

    /*
     * 获取最后一个元素
     */
    second: function() {
      index = length - 1;
      return items[index];
    },

    /*
     * 获取前一个元素
     */
    prev: function() {
      if (--index > 0) {
        return items[index];
      } else {
        index = 0;
        return items[index];
      }
    },

    /*
     * 获取后一个元素
     */
    next: function() {
      if (++index < length) {
        return items[index];
      } else {
        index = length - 1;
        return items[index];
      }
    },

    /*
     * 获取某一个元素
     */
    get: function(num) {
      index = num >= 0 ? num % length : num % length + length;
      return items[index];
    },

    /*
     * 对每一个元素执行某一个方法
     */
    dealEach: function(fn) {
      var args = splice.call(arguments, 1);

      for (var i = 0; i < length; i++) {
        fn.apply(items[i], args);
      }
    },

    /*
     * 对某一个元素执行某一个方法
     */
    dealItem: function(num, fn) {
      var args = splice.call(arguments, 2);
      // 通过this.get方法设置index索引值
      fn.apply(this.get(num), args);
    },

    /*
     * 排他方式处理某一个元素
     */
    exclusive: function(num, allFn, numFn) {
      // 对所有元素执行回调函数
      this.dealEach(allFn);

      // 如果num为数组
      if (Object.prototype.toString.call(num) === '[object Array]') {
        for (var i = 0; i < num.length; i++) {
          this.dealItem(num[i], numFn);
        }
      } else {
        this.dealItem(num, numFn);
      }
    }
  };
};

var test =  Iterator('li', 'container');

console.log(test.first());
console.log(test.prev());
console.log(test.next());
console.log(test.get(2000));

// 处理所有元素
test.dealEach(function(text, color) {
  this.innerHTML = text;
  this.style.background = color;
}, 'test', 'pink');

// 排他思想处理第3个与第4个元素
test.exclusive([2, 3], function() {
  this.innerHTML = '被排除的';
  this.style.background = 'green';
}, function() {
  this.innerHTML = '选中的';
  this.style.background = 'red';
});

// 测试HTML

/*<ul id="container">
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>*/

forEach的实现

'use strict';

var forEach = function(arr, fn) {
  for (var i = 0; i < arr.length; i++) {
    fn(arr[i], i, arr);
  }
};

forEach([1,2,3,4], function(item, i, arr) {
  console.log(item, i, arr);
});

对象迭代器的实现

'use strict';

var eachObject = function(obj, fn) {
  for (var i in obj) {
    fn(obj[i], i, obj);
  }
};

eachObject({a: '123', b: '456', c: '789'}, function(item, key, obj) {
  console.log(item, key, obj);
});

取值器

'use strict';

var a = {
  common: {},
  client: {
    user: {
      username: 'berwin',
      uid: '123'
    }
  },
  server: {}
};

// 如果不知道服务器是否会将该属性或者该属性的上级属性正确的打印到页面中,直接获取属性会导致报错,所以每次操作都要一层一层做安全检查 var test = a && a.client && a.client.user && a.client.user.username;

// 通过迭代器我们即可减少编写这类校验代码
var getter = function(data, key) {
  if (!data) return undefined;

  var result = data;

  var keys = key.split('.');

  for (var i = 0; i < keys.length; i++) {
    if (result[keys[i]]) {
      result = result[keys[i]];
    } else {
      return undefined;
    }
  }

  return result;
}

console.log( getter(a, 'client.user.username') ); // berwin
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1 场景问题# 1.1 工资表数据的整合## 考虑这样一个实际应用:整合工资表数据。 这个项目的背景是这样的,项目...
    七寸知架构阅读 7,366评论 0 53
  • 目录 本文的结构如下: 引言 什么是迭代器模式 模式的结构 典型代码 代码示例 优点和缺点 适用环境 模式应用 一...
    w1992wishes阅读 3,547评论 0 1
  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 9,404评论 1 15
  • 花了两个晚上的时间,重新整理并修改了上周的作业,并把它发表在了公众号上,今天转发后,好评满满。我也很开心,我终于迈...
    Lily5566阅读 1,310评论 1 0
  • 器材:vivox6 后期:黄油相机 春天害我得了一场相思病。 南国难得的春阳,终于见到阳光下的水仙,那种亮亮的光和...
    语花慢阅读 1,832评论 4 4

友情链接更多精彩内容