jQuery原型上有個each()方法,但其中有個陷阱。
我們都知道jQuery中each的用法是
$.each()
,那原型上的方法又必須要new一個執行個體對象才能調用,這樣的話根據我們在入口函數篇的寫法來看,頂多采用
$().each()
才能成功調用,很明顯不對勁。
仔細一看,jQuery源碼中原型上的each好像隻是調用了一個each工具方法,再往下劃,在extend中找到了each方法的實作。
而這個extend就是我們之前 面向對象思想優化代碼 篇中實作過的工具方法類嘛。
我們隻需要将each方法的實作放到extend工具類中,便可實作
$.each()
//采用這種方式既可通過類調用添加靜态方法 例如:dQuery.extend({}),
//也可通過對象調用添加執行個體方法 例如:var a = new dQuery(); a.extend({})
//更重要的一點:此時的this就是dQuery,周遊給dQuery對象添加所有的工具方法,這樣就可以實作$.each這樣的操作了
dQuery.extend = dQuery.prototype.extend = function (obj){
for(var key in obj){
this[key] = obj[key];
}
}
//調用dQuery上的extend方法,傳入一個對象,對象中全是工具方法
//裝工具方法
dQuery.extend({
//判斷方法
isFunction : function(sel){
return typeof sel === "function";
},
//封裝判斷字元串和代碼片段的方法
isString : function(str){
return typeof str === "string";
},
isHtml : function(str){
return str.charAt(0) == "<" &&
str.charAt(str.length-1) == ">" &&
str.length >=3
},
//封裝判斷對象 數組 window的方法
isObject : function(sel){
return typeof sel === "object"
},
isWindow : function (sel){
return sel === window;
},
isArray : function(sel){
if(dQuery.isObject(sel)&&
!dQuery.isWindow(sel)&&
"length" in sel){
return true;
}
return false;
},
//去除傳入字元串的空格
trim : function (str){
if(!dQuery.isString(str)){
return str;
}
if(str.trim){
return str.trim();
}else{
return str.replace(/^\s+|\s+$/g,"")
}
},
//函數處理
ready : function(fn){
//判斷DOM是否加載完畢
if(document.readyState == "complete"){
fn();
}
else if(document.addEventListener){ //進階浏覽器
document.addEventListener("DOMContentLoaded",function(){
fn();
})
}
else{ //lowB浏覽器
document.attachEvent("onreadystatechange",function(){
if(document.readyState == "complete"){
fn();
}
})
}
},
each:function(obj,fn){
//真數組
if(dQuery.isArray(obj)){
for(var i=0;i < obj.length;i++){
fn(i,obj[i]); //回調函數
}
}
//僞數組
else if(dQuery.isObject(obj)){
for(var key in obj ){
fn(key,obj[key]);
}
}
}
})