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]);
}
}
}
})