在 葉小釵 的博客中看到一段關於遍歷的代碼 jQuery 中的each 不僅僅是用來遍歷jQuery對象,還可以用來作為合併介面。 其中就利用了$.each(fn)的特性,jQuery 源碼中 : 為obj 執行回調函數 callback。 裡面的巧妙之處在於: 在為obj執行回調函數的時候,回調函 ...
在 葉小釵 的博客中看到一段關於遍歷的代碼
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');
})