JQuery源碼分析閱讀

原文鏈接:https://blog.csdn.net/zuoxiaolong8810/article/details/8546527

轉載自:https://blog.csdn.net/zuoxiaolong8810/article/details/8546527

 

/*
 * my-jquery-1.0
 */
/*
 * 網上也有很多實現的版本,不過這是我在我自己的理解下寫的,加上註釋,希望可以解釋清楚。
*/
/*
 * 整個jquery包含在一個匿名函數中,專業點叫閉包,就是下面的形式,如(function(window,undefined){}(window))。
 * 閉包的定義在這裏不太容易講清楚,我只說下這樣說的好處。
 * 1.使整個jquery中定義的變量成爲局域變量,不會影響全局變量,個人覺得這也是jquery被成爲輕量級的原因之一。
 * 2.增加jquery運行速度,因爲局域變量運行速度高於全局變量。
 * 3.就像你看到,傳入的window和undefined,可以自定義名字,方便編寫。當然,現在你看到的仍是原來的寫法,但是你可以看看jquery的min版本,一定是壓縮的。
*/
(function( window, undefined ) {
var 
    /*jquery的定義,我們平時用的$和jQuery就是它。這裏可以看出來真正的jQuery的對象是init方法產生的。
     *這樣做採用了工廠模式,創建jQuery對象時不需要再new一個對象了。所以你可以發現,我們創建jQuery對象的方式是$(selector)或者是jQuery(selector)
     *原版的jQuery定義方法多了個上下文參數context,此處我省略了。
    */
    jQuery = function(selector){
        return new jQuery.fn.init(selector);
    },
    /*
     * 引用數據、對象以及字符串的方法
    */
    core_push = Array.prototype.push,
    core_slice = Array.prototype.slice,
    core_indexOf = Array.prototype.indexOf,
    core_toString = Object.prototype.toString,
    core_hasOwn = Object.prototype.hasOwnProperty,
    core_trim = String.prototype.trim;
    /*
     * jQuery對象的定義,這裏去掉了所有的屬性,只留下了init()。
     * jQuery的選擇器採用了Sizzle,這裏省略了,可以看出我只簡單的返回了一個查詢ID的方式。
     * jQuery的對象並不是這樣簡單的賦給了對象的一個屬性,而是創建了一個數組。在這裏忽略那些,只是賦給了obj屬性。
     * 這裏jQuery將原型賦給了jQuery的fn屬性,所以我們如果要給jQuery對象擴展,只需要對jQuery.fn擴展就行。
    */
    jQuery.fn = jQuery.prototype = {
        init:function(selector){
                this.obj = window.document.getElementById(selector);
                return this;
        }
    };
    /*
     * 將jQuery的原型賦給init,這樣是爲了可以讓jQuery對象,也就是init對象可以使用jQuery的擴展方法。
    */
    jQuery.fn.init.prototype = jQuery.fn;
    /*
     * jQuery的擴展方法,這個是jQuery的原版方法,我沒做更改。
     * 方法的邏輯在這裏不再說明,方法的效果就是,我們使用jQuery.extend可以擴展jQuery,而jQuery.fn.extend可以擴展jQuery對象。
    */
    jQuery.extend = jQuery.fn.extend = function() {
        var options, name, src, copy, copyIsArray, clone,
            target = arguments[0] || {},
            i = 1,
            length = arguments.length,
            deep = false;
 
        // Handle a deep copy situation
        if ( typeof target === "boolean" ) {
            deep = target;
            target = arguments[1] || {};
            // skip the boolean and the target
            i = 2;
        }
 
        // Handle case when target is a string or something (possible in deep copy)
        if ( typeof target !== "object" && !d.isFunction(target) ) {
            target = {};
        }
 
        // extend jQuery itself if only one argument is passed
        if ( length === i ) {
            target = this;
            --i;
        }
 
        for ( ; i < length; i++ ) {
            // Only deal with non-null/undefined values
            if ( (options = arguments[ i ]) != null ) {
                // Extend the base object
                for ( name in options ) {
                    src = target[ name ];
                    copy = options[ name ];
 
                    // Prevent never-ending loop
                    if ( target === copy ) {
                        continue;
                    }
 
                    // Recurse if we're merging plain objects or arrays
                    if ( deep && copy && ( d.isPlainObject(copy) || (copyIsArray = d.isArray(copy)) ) ) {
                        if ( copyIsArray ) {
                            copyIsArray = false;
                            clone = src && d.isArray(src) ? src : [];
 
                        } else {
                            clone = src && d.isPlainObject(src) ? src : {};
                        }
 
                        // Never move original objects, clone them
                        target[ name ] = d.extend( deep, clone, copy );
 
                    // Don't bring in undefined values
                    } else if ( copy !== undefined ) {
                        target[ name ] = copy;
                    }
                }
            }
        }
 
        // Return the modified object
        return target;
    };
    /*
     * 這裏實現了簡單的ready綁定序列。
    */
    jQuery.extend({
        isReady:false,//文檔加載是否完成的標識
        readyList:[],//函數序列
        //以下爲工具方法,可忽略
        isArray : Array.isArray || function( obj ) {
            return jQuery.type(obj) === "array";
        },
 
        isWindow : function( obj ) {
            return obj != null && obj == obj.window;
        },
 
        isNumeric : function( obj ) {
            return !isNaN( parseFloat(obj) ) && isFinite( obj );
        },
 
        type : function( obj ) {
            return obj == null ?
                String( obj ) :
                class2type[ core_toString.call(obj) ] || "object";
        },
 
        isPlainObject : function( obj ) {
            // Must be an Object.
            // Because of IE, we also have to check the presence of the constructor property.
            // Make sure that DOM nodes and window objects don't pass through, as well
            if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
                return false;
            }
 
            try {
                // Not own constructor property must be Object
                if ( obj.constructor &&
                    !core_hasOwn.call(obj, "constructor") &&
                    !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
                    return false;
                }
            } catch ( e ) {
                // IE8,9 Will throw exceptions on certain host objects #9897
                return false;
            }
 
            // Own properties are enumerated firstly, so to speed up,
            // if last one is own, then all properties are own.
 
            var key;
            for ( key in obj ) {}
 
            return key === undefined || core_hasOwn.call( obj, key );
        },
        isFunction : function(obj){
            if(obj && typeof obj == 'function'){
                return true;
            }
            return false;
        },
        //onload事件實現
        ready : function(fn){
                //如果是函數,加入到函數序列
                if(fn && typeof fn == 'function' ){
                    jQuery.readyList.push(fn);
                }
                //文檔加載完成,執行函數序列。
                if(jQuery.isReady){
                    for(var i = 0;i < jQuery.readyList.length ;i++){
                        fn = jQuery.readyList[i];
                        jQuery.callback(fn);
                    }
                    return jQuery;
                }
            },
        //回調
        callback : function(fn){
            fn.call(document,jQuery);
        }
    });
    //模擬實現jQuery的html方法
    jQuery.fn.extend({
    html : function(html){
        if(html && typeof html == 'string'){
           this.obj.innerHTML = html;
           return this;
        }
        return this.obj.innerHTML;
    }
    });
    //導出對象
    window.$ = window.jQuery = jQuery;
    //判斷加載是否完成
    var top = false;
    try {
        top = window.frameElement == null && document.documentElement;
    } catch(e) {}
    if ( top && top.doScroll ) {
        (function doScrollCheck() {
            try {
                top.doScroll("left");
                jQuery.isReady = true;
                jQuery.ready();
            } catch(e) {
                setTimeout( doScrollCheck, 50 );
            }
        })();
    }
}(window));

》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

<html>
<head>
<script src="my-jquery-1.0.js" type="text/javascript"></script>
<script type="text/javascript">
    $.extend({
        testExtend:function(){
            alert('extend success');
        }
    });
    $.ready(function(){
        alert($("test").html());
        $.testExtend();
    });
    $.ready(function(){
        $("test").html("modify success");
    });
    $.ready(function(){
        alert($("test").html());
    });
</script>
</head>
<body>
    <div id="test">jquery src</div>
</body>
</html>

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章