我們研究一下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;
為了幫助理解,請再看下面的例子:
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函數。
前面四小塊代碼很簡單——當參數分別為空、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 };
因為插件會添加屬性到所有已存在的實體和將來要新建的實體,所以如果想針對地對某一對象添加屬性,可以用靜態屬性:
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);