jQuery基本框架解析


我們研究一下jQuery的源碼

編碼方法很簡單。 下面是全部代碼的開頭和結尾。

(function( window, undefined ) {
 
var document = window.document,
    navigator = window.navigator,
    location = window.location;
 
    [...] // The main sources are here
     
window.jQuery = window.$ = jQuery;
})(window);

  

核心

 下面是主要代碼的縮減版,可以看到很多塊代碼。

var jQuery = (
      function () {   
var jQuery = function ( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery );};     // Map over jQuery in case of overwrite    _jQuery = window.jQuery,     // Map over the $ in case of overwrite    _$ = window.$,    // A central reference to the root jQuery(document)    rootjQuery,    [...]       rootjQuery = jQuery(document);    [...]    return jQuery; })();

上面代碼中jQuery對象的構造函數, jQuery、$和 rootjQuery(一個指向文檔的jQuery對象)。

 

下面代碼解釋為什么我們可以用"."和"[]"操作變量jQuery對象。

trim = String.prototype.trim,
indexOf = Array.prototype.indexOf,

 對象的構造

這里是jQuery函數的最神聖的地方。jQuery的prototype的魔力隱藏在這里。

var jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
    return new jQuery.fn.init( selector, context, rootjQuery );
},

當你調用jQuery函數式,緊接着新建一個“jQuery.fn.init” 對象並返回。 參看下面代碼:

jQuery.fn = jQuery.prototype = {
    constructor: jQuery,
    init: function( selector, context, rootjQuery ) {
        [...]
    }
    [...]
}
 
// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;
至此, 我們可以知道jQuery.fn等同於jQuery prototype,同時,jQuery.fn.init.prototype指向jQuery prototype,  jQuery.fn.init.prototype constructor指向jQuery。這些信息給了我們一個有意思的結論:輸入以下代碼
$(document) instanceof jQuery; // true
$(document) instanceof jQuery.fn.init; // true

為了幫助理解,請再看下面的例子:

var Init = function () {
    console.log('[Init]');
};
 
var jQuery = function () {
    console.log('[jQuery]');
    return new Init();
};
 
Init.prototype = jQuery.prototype = {
    constructor: jQuery
};
 
var $elem = jQuery(); // [jQuery] , [Init]
 
console.log( $elem instanceof jQuery ); // true
console.log( $elem instanceof Init   ); // true

可以看出,所有的結構都在一個jQuery.fn.init對象函數里,而jQuery是生產所有jQuery.fn.init對象的工廠。

 解析參數

有很多種應用jQuery函數的方法:

$(function () { alert('READY!') }); // Function to be executed only when loading a DOM
$(document.getElementById('test')); // link on the element
$('<div />'); // create new element
$('<div />', { title: 'test' }); // create new element with attributes
 
// Supports all imaginable and unimaginable css-selectors:
$('#element'); // element with ip "element"
$('.element', $previous ); // Find all elements with a class element in $ previous
$("div[name=city]:visible:has(p)");

讓我們進一步分析jQuery.fn.init函數。

 

init: function( selector, context, rootjQuery ) {
    if ( !selector ) return this;
 
    // Handle $(DOMElement)
    if ( selector.nodeType ) return this = selector;
 
    // The body element only exists once, optimize finding it
    if ( selector === "body" && !context ) return this = document.body;
 
    if ( jQuery.isFunction( selector ) ) {
        return rootjQuery.ready( selector );
    }
 
    // Handle HTML strings
    if ( typeof selector === "string" ) {
        // Verify a match, and that no context was specified for #id
        if ( selector.match(quickExpr) ) {
            if ( match[1] ) {
                return createNewDomElement( match[1] );
            } else {
                return getById( match[2] )
            }
        } else {
            return jQuery( context ).find( selector );
        }
    }
},

前面四小塊代碼很簡單——當參數分別為空、DOM元素、“body”字符串時如何處理。

 

Plug-ins Development  創建插件

 

很多專業人士都知道js的類可以很簡單地通過prototypes進行擴展。

var MyClass = function () {
    // constructor
};
 
MyClass.prototype = {
    // prototype
};
 
var instance = new MyClass();
 
// We can extend the class prototype and new features will be added to all entities, even those whichvare already created
 
MyClass.prototype.plugin = function () {
    console.log("He's alive!");
};
 
instance.plugin(); // He's alive!

 

我們可以用同樣方法對標准JQuery進行擴展。

jQuery.prototype.plugin = function () {
    // Here is my plugin
};

 

但是,我們已知fn等於jQuery.prototype,所以可以簡寫如下:
jQuery.fn.plugin = function () {
    // Here is my plugin
    // This here refers to jquery-object, from which the method is called
};

 

因為插件會添加屬性到所有已存在的實體和將來要新建的實體,所以如果想針對地對某一對象添加屬性,可以用靜態屬性:

jQuery.plugin = function () {
    // Here is my plugin
};

小插件的最佳模式:

new function (document, $, undefined) {
     
    var privateMethod = function () {
        // private method, used for plugin
    };
     
    $.fn.myPlugin = function () {
         
    };
     
    // and if you need a method that is not bound to the dom-elements:
    $.myPlugin = function () {
         
    };
     
}(document, jQuery);

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM