• JavaScript迭代器模式


    1 什么是迭代器模式

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

    迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。

    JavaScript有内置的迭代器Array.prototype.forEach

    2 实现一个迭代器

    下面来实现一个迭代器函数eacheach函数接受2个参数,第一个为一个数组,第二个为每一次循环后要触发的回调函数,代码如下:

    function each(arr, callback) {
      // 对arr循环遍历,每一次遍历调用callback
      for (let i = 0, l = arr.length; i < l; i++) {
        callback.call(arr[i], i, arr[i]);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3 内部迭代器和外部迭代器

    3.1 内部迭代器

    刚才编写的each函数属于内部迭代器,因为在each函数内部已经定义好了迭代的规则,外部只需要调用一次就可以。

    内部迭代器不关心具体的实现,因此调用时非常方便,但是这也刚好是内部迭代器的缺点,因为内部迭代器的迭代规则已经被提前规定好了,如果我们想同时迭代2个数组,上面的each函数是无法实现的。

    比如,判断2个数组里元素的值是否完全相等,不能改动each函数,代码如下:

    function compare(arr1, arr2) {
      // 如果两个数组长度不相同,不可能相等
      if (arr1.length !== arr2.length) {
        console.log("arr1和arr2不相等");
        return;
      }
      each(arr1, function (i, n) {
        // i为arr1每一项索引,n为arr1每项的值
        if (n !== arr2[i]) {
          console.log("arr1和arr2不相等");
          return;
        }
        console.log("arr1和arr2相等");
      });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3.2 外部迭代器

    外部迭代器必须显式地请求迭代下一个元素,它增加了一些调用的复杂度,但相对也增强了迭代器的灵活性,我们可以手工控制迭代的过程或者顺序。

    实现一个外部迭代器:

    function Iterator(obj) {
      var current = 0; // 记录当前的索引
    
      // 下一个位置的索引
      var next = function () {
        current += 1;
      };
    
      // 是否已经迭代完成
      var isDone = function () {
        return current >= obj.length;
      };
    
      // 获取当前位置的数据
      var getCurrentItem = function () {
        return obj[current];
      };
    
      return {
        next,
        isDone,
        getCurrentItem,
      };
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    根据以上外部迭代器,我们可以这样改写compare函数:

    function compare(iterator1, iterator2) {
      while (!iterator1.isDone() && !iterator2.isDone()) {
        if (iterator1.getCurrentItem() !== iterator2.getCurrentItem()) {
          console.log("arr1和arr2不相等");
          return;
        }
        iterator1.next();
        iterator2.next();
      }
      console.log("arr1和arr2相等");
    }
    
    var iterator1 = Iterator([1, 2, 3]);
    var iterator2 = Iterator([2, 3, 4]);
    
    compare(iterator1, iterator2); // arr1和arr2不相等
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    外部迭代器虽然调用方式相对复杂,但它的适用面更广,也能满足更多变的需求。

    4 迭代类数组对象和字面量对象

    迭代器模式不仅可以迭代数组,还可以迭代一些类数组的对象,比如arguments{ 0: "a", 1: "b" }等。无论是内部迭代器还是外部迭代器,只要被迭代的聚合对象拥有length属性而且可以用下标访问,那它就可以被迭代。

    JavaScript中,for in语句可以用来迭代普通字面量对象的属性。jQuery中提供了$.each函数来封装各种迭代行为:

    $.each = function (obj, callback) {
      var value,
        i = 0,
        length = obj.length,
        isArray = isArraylike(obj);
      if (isArray) {
        // 迭代类数组
        for (; i < length; i++) {
          value = callback.call(obj[i], i, obj[i]);
          if (value === false) {
            break;
          }
        }
      } else {
        for (i in obj) {
          // 迭代 object 对象
          value = callback.call(obj[i], i, obj[i]);
          if (value === false) {
            break;
          }
        }
      }
      return obj;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  • 相关阅读:
    idea(添加jsp文件模板)
    在java中操作Redis
    全面解析找不到msvcr100.dll的解决方法,快速修复系统msvcr100.dll丢失问题!
    可视化3个10分类
    目标检测YOLO实战应用案例100讲-面向路边停车场景的目标检测(中)
    【剑指offer】链表06-JZ23 链表中环的入口结点
    MyBatis 中如何实现分页 ?
    SVN 服务器建立
    java项目-基于SSM实现物流信息管理系统
    Go的数据结构(感谢韩老师)
  • 原文地址:https://blog.csdn.net/m0_46612221/article/details/133589138