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;
为了帮助理解,请再看下面的例子:
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);