jQuery 迭代器

在 叶小钗 的博客中看到一段关于遍历的代码

    var ajQuery = {};

function dir(elem, dir, until) {
  var matched = [],
    truncate = until !== undefined;
  while ((elem = elem[dir]) && elem.nodeType !== 9) {
    if (elem.nodeType === 1) {
      if (truncate) {
        if (elem.nodeName.toLowerCase() == until || elem.className == until) {
          break;
        }
      }
      matched.push(elem);
    }
  }
  return matched;
}

// 迭代器
  jQuery.each({
    parent: function(elem) {
      var parent = elem.parentNode;
      return parent && parent.nodeType !== 11 ? parent : null;
    },
    parents: function(elem) {
      return dir(elem, "parentNode");
    },
    parentsUntil: function(elem, until) {
      return dir(elem, "parentNode", until);
    }
  }, function(name, fn) {
    ajQuery[name] = function(until, selector) {
      return  fn(until, selector);
    };
  });


  $("#test1").click(function() {
    var item = $('.item-1');
    alert(item.parent()[0])
    alert(item.parents().length)
    alert(item.parentsUntil('body').length)
  })

  $("#test2").click(function() {
    var item = document.querySelectorAll('.item-1')[0]
    alert(ajQuery.parent(item))
    alert(ajQuery.parents(item).length)
    alert(ajQuery.parentsUntil(item, 'body').length)
  })


jQuery 中的each 不仅仅是用来遍历jQuery对象,还可以用来作为合并接口。

jQuery.each({  
   parent: function(elem) {}, 
   parents: function(elem) {},  
   nextAll: function(elem) {},  
   prevAll: function(elem) {},  
   ................
}, function(name, fn) {  
     api[name] = function(until, selector){    
  };
});

其中就利用了$.each(fn)的特性,jQuery 源码中 :

 each: function( obj, callback, args ){}

为obj 执行回调函数 callback。

 

里面的巧妙之处在于:

在为obj执行回调函数的时候,回调函数为新的对象 ajQuery{},绑定了新的属性(或方法)

function(name, fn) {
    ajQuery[name] = function(until, selector) {
      return  fn(until, selector);
    };
  }

测试:

jQuery.each({
    say: function(cont){
      console.log(cont);
    }
}, function(name, fn) {
    ajQuery[name] = function(until, selector) {
      // 传递fn参数
      return  fn(until, selector);
    };
});

$("#test1").click(function() {
    ajQuery.say('oooooooo'); // oooooooo
})

 

 所以根据这个推论,总结each的原理:

1. 遍历obj对象;

2. 为callback传参;

3. 为每个obj[i],绑定callback

模拟写了个版本:

    o = {};
    test = {
        fn1: function(){},
        fn2: function(){},
        getDom: function(dom, fn){
            var t = document.getElementById(dom)
            return t.onclick = function(){
                fn()
            } 
        },
        each: function(c, fn){
            for(k in c){
                fn.call(c[k],k,c[k]);
            }
            return c;
        }
    }

    test.each({
        say: function(cont){
            console.log(cont)
        },
        walk: function(length){
            console.log('walk '+length);
        }
    }, function(name, fn) {  
       o[name] = function(name){    
               return fn(name);     
       }
    })

// 调用
test.getDom('btn', function(){
  o.say('aaaaa');
})

 
原文地址:https://www.cnblogs.com/dongcheck/p/5784756.html