jQuery中的迭代器

迭代器模式无非就是循环访问聚合对象中的各个元素。比如jQuery中的$.each函数,其中回调函数中的参数i为当前索引,n为当前元素,代码如下:

  1. $.each( [1, 2, 3], function( i, n ){
  2. console.log( '当前下标为: '+ i );
  3. console.log( '当前值为:' + n );
  4. });

实现自己的迭代器

  1. var each = function (arr, fn) {
  2. for (var i = 0, len = arr.length; i < len; i++) {
  3. fn.apply(arr, [i, arr[i]]);
  4. }
  5. }
  6. each([1,2,3], function (i, e) {
  7. console.log(this)
  8. console.warn({e, i})
  9. })

内部迭代器与外部迭代器

  • 内部迭代器
    即如上一样,它完全接手整个迭代过程,外部只需要一次初始调用。
  • 外部迭代器
    外部迭代器必须显式地请求迭代下一个元素。
    外部迭代器增加了一些调用的复杂度,但相对也增强了迭代器的灵活性,我们可以手工控制迭代的过程或者顺序。
  1. var Iterator = function (obj) {
  2. var current = 0;
  3. var next = function () {
  4. current = current + 1;
  5. };
  6. var isDone = function () {
  7. return current >= obj.length;
  8. };
  9. var getCurrentItem = function () {
  10. return obj[current]
  11. };
  12. return {
  13. next,
  14. isDone,
  15. getCurrentItem,
  16. length: obj.length,
  17. };
  18. };
  19. var compare = function (iteratorA, iteratorB) {
  20. if (iteratorA.length !== iteratorB.length) {
  21. return false;
  22. }
  23. while (!iteratorA.isDone() && !iteratorB.isDone()) {
  24. if (iteratorA.getCurrentItem() !== iteratorB.getCurrentItem()) {
  25. return false;
  26. };
  27. iteratorA.next();
  28. iteratorB.next();
  29. }
  30. return true;
  31. }
  32. var arr = ['a', 'b', 'c', 'd'];
  33. var arr2 = ['a', 'b', 'c', 'd'];
  34. console.warn(compare(Iterator(arr), Iterator(arr2))); // true

外部迭代器虽然调用方式相对复杂,但它的适用面更广,也能满足更多变的需求。内部迭代器和外部迭代器在实际生产中没有优劣之分,究竟使用哪个要根据需求场景而定。

迭代器模式的应用举例

  • 未使用迭代器前的业务代码
  1. var getUploadObj = function () {
  2. try {
  3. return new ActiveXObject("TXFTNActiveX.FTNUpload"); // IE上传控件
  4. } catch (e) {
  5. if (supportFlash()) { // supportFlash函数未提供
  6. var str = '&lt;object type="application/x-shockwave-flash"&gt;&lt;/object&gt;';
  7. return $(str).appendTo($('body'));
  8. } else {
  9. var str = '&lt;input name="file" type="file"/&gt;'; // 表单上传
  10. return $(str).appendTo($('body'));
  11. }
  12. }
  13. };
  • 使用迭代器模式进行优化
  1. var getActiveUploadObj = function () {
  2. try {
  3. return new ActiveXObject("TXFTNActiveX.FTNUpload"); // IE上传控件
  4. } catch (e) {
  5. return false;
  6. }
  7. };
  8. var getFlashUploadObj = function () {
  9. if (supportFlash()) { // supportFlash函数未提供
  10. var str = '&lt;object type="application/x-shockwave-flash"&gt;&lt;/object&gt;';
  11. return $(str).appendTo($('body'));
  12. }
  13. return false;
  14. };
  15. var getFormUpladObj = function () {
  16. var str = '&lt;input name="file" type="file" class="ui-file"/&gt;'; // 表单上传
  17. return $(str).appendTo($('body'));
  18. };
  19. var iteratorUploadObj = function (arr) {
  20. for (var i = 0, len = arr.length; i < len; i++) {
  21. var uploadObj = arr[i]();
  22. if (uploadObj) {
  23. return uploadObj;
  24. }
  25. }
  26. }
  27. // 使用
  28. var uploadObj = iteratorUploadObj(getActiveUploadObj, getFlashUploadObj, getFormUpladObj);

迭代器模式是一种相对简单的模式,简单到很多时候我们都不认为它是一种设计模式。目前的绝大部分语言都内置了迭代器。