天天看點

手撸jQuery源碼:jQuery屬性上的方法(續)

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