在 叶小钗 的博客中看到一段关于遍历的代码
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');
})