jquery源码分析

来源:互联网 发布:java验证码识别算法 编辑:程序博客网 时间:2024/09/21 08:15

         前段时间上班无聊之时,研究了下jQuery的源码。现在记录下自己的成果,分享一下。

         下面是我自己琢磨和编写的jquery模型,里面有我所写的注释。

[javascript] view plain copy
  1. /* 
  2.  * my-jquery-1.0 
  3.  */  
  4. /* 
  5.  * 网上也有很多实现的版本,不过这是我在我自己的理解下写的,加上注释,希望可以解释清楚。 
  6. */  
  7. /* 
  8.  * 整个jquery包含在一个匿名函数中,专业点叫闭包,就是下面的形式,如(function(window,undefined){}(window))。 
  9.  * 闭包的定义在这里不太容易讲清楚,我只说下这样说的好处。 
  10.  * 1.使整个jquery中定义的变量成为局域变量,不会影响全局变量,个人觉得这也是jquery被成为轻量级的原因之一。 
  11.  * 2.增加jquery运行速度,因为局域变量运行速度高于全局变量。 
  12.  * 3.就像你看到,传入的window和undefined,可以自定义名字,方便编写。当然,现在你看到的仍是原来的写法,但是你可以看看jquery的min版本,一定是压缩的。 
  13. */  
  14. (function( window, undefined ) {  
  15. var   
  16.     /*jquery的定义,我们平时用的$和jQuery就是它。这里可以看出来真正的jQuery的对象是init方法产生的。 
  17.      *这样做采用了工厂模式,创建jQuery对象时不需要再new一个对象了。所以你可以发现,我们创建jQuery对象的方式是$(selector)或者是jQuery(selector) 
  18.      *原版的jQuery定义方法多了个上下文参数context,此处我省略了。 
  19.     */  
  20.     jQuery = function(selector){  
  21.         return new jQuery.fn.init(selector);  
  22.     },  
  23.     /* 
  24.      * 引用数据、对象以及字符串的方法 
  25.     */  
  26.     core_push = Array.prototype.push,  
  27.     core_slice = Array.prototype.slice,  
  28.     core_indexOf = Array.prototype.indexOf,  
  29.     core_toString = Object.prototype.toString,  
  30.     core_hasOwn = Object.prototype.hasOwnProperty,  
  31.     core_trim = String.prototype.trim;  
  32.     /* 
  33.      * jQuery对象的定义,这里去掉了所有的属性,只留下了init()。 
  34.      * jQuery的选择器采用了Sizzle,这里省略了,可以看出我只简单的返回了一个查询ID的方式。 
  35.      * jQuery的对象并不是这样简单的赋给了对象的一个属性,而是创建了一个数组。在这里忽略那些,只是赋给了obj属性。 
  36.      * 这里jQuery将原型赋给了jQuery的fn属性,所以我们如果要给jQuery对象扩展,只需要对jQuery.fn扩展就行。 
  37.     */  
  38.     jQuery.fn = jQuery.prototype = {  
  39.         init:function(selector){  
  40.                 this.obj = window.document.getElementById(selector);  
  41.                 return this;  
  42.         }  
  43.     };  
  44.     /* 
  45.      * 将jQuery的原型赋给init,这样是为了可以让jQuery对象,也就是init对象可以使用jQuery的扩展方法。 
  46.     */  
  47.     jQuery.fn.init.prototype = jQuery.fn;  
  48.     /* 
  49.      * jQuery的扩展方法,这个是jQuery的原版方法,我没做更改。 
  50.      * 方法的逻辑在这里不再说明,方法的效果就是,我们使用jQuery.extend可以扩展jQuery,而jQuery.fn.extend可以扩展jQuery对象。 
  51.     */  
  52.     jQuery.extend = jQuery.fn.extend = function() {  
  53.         var options, name, src, copy, copyIsArray, clone,  
  54.             target = arguments[0] || {},  
  55.             i = 1,  
  56.             length = arguments.length,  
  57.             deep = false;  
  58.   
  59.         // Handle a deep copy situation  
  60.         if ( typeof target === "boolean" ) {  
  61.             deep = target;  
  62.             target = arguments[1] || {};  
  63.             // skip the boolean and the target  
  64.             i = 2;  
  65.         }  
  66.   
  67.         // Handle case when target is a string or something (possible in deep copy)  
  68.         if ( typeof target !== "object" && !d.isFunction(target) ) {  
  69.             target = {};  
  70.         }  
  71.   
  72.         // extend jQuery itself if only one argument is passed  
  73.         if ( length === i ) {  
  74.             target = this;  
  75.             --i;  
  76.         }  
  77.   
  78.         for ( ; i < length; i++ ) {  
  79.             // Only deal with non-null/undefined values  
  80.             if ( (options = arguments[ i ]) != null ) {  
  81.                 // Extend the base object  
  82.                 for ( name in options ) {  
  83.                     src = target[ name ];  
  84.                     copy = options[ name ];  
  85.   
  86.                     // Prevent never-ending loop  
  87.                     if ( target === copy ) {  
  88.                         continue;  
  89.                     }  
  90.   
  91.                     // Recurse if we're merging plain objects or arrays  
  92.                     if ( deep && copy && ( d.isPlainObject(copy) || (copyIsArray = d.isArray(copy)) ) ) {  
  93.                         if ( copyIsArray ) {  
  94.                             copyIsArray = false;  
  95.                             clone = src && d.isArray(src) ? src : [];  
  96.   
  97.                         } else {  
  98.                             clone = src && d.isPlainObject(src) ? src : {};  
  99.                         }  
  100.   
  101.                         // Never move original objects, clone them  
  102.                         target[ name ] = d.extend( deep, clone, copy );  
  103.   
  104.                     // Don't bring in undefined values  
  105.                     } else if ( copy !== undefined ) {  
  106.                         target[ name ] = copy;  
  107.                     }  
  108.                 }  
  109.             }  
  110.         }  
  111.   
  112.         // Return the modified object  
  113.         return target;  
  114.     };  
  115.     /* 
  116.      * 这里实现了简单的ready绑定序列。 
  117.     */  
  118.     jQuery.extend({  
  119.         isReady:false,//文档加载是否完成的标识  
  120.         readyList:[],//函数序列  
  121.         //以下为工具方法,可忽略  
  122.         isArray : Array.isArray || function( obj ) {  
  123.             return jQuery.type(obj) === "array";  
  124.         },  
  125.   
  126.         isWindow : function( obj ) {  
  127.             return obj != null && obj == obj.window;  
  128.         },  
  129.   
  130.         isNumeric : function( obj ) {  
  131.             return !isNaN( parseFloat(obj) ) && isFinite( obj );  
  132.         },  
  133.   
  134.         type : function( obj ) {  
  135.             return obj == null ?  
  136.                 String( obj ) :  
  137.                 class2type[ core_toString.call(obj) ] || "object";  
  138.         },  
  139.   
  140.         isPlainObject : function( obj ) {  
  141.             // Must be an Object.  
  142.             // Because of IE, we also have to check the presence of the constructor property.  
  143.             // Make sure that DOM nodes and window objects don't pass through, as well  
  144.             if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {  
  145.                 return false;  
  146.             }  
  147.   
  148.             try {  
  149.                 // Not own constructor property must be Object  
  150.                 if ( obj.constructor &&  
  151.                     !core_hasOwn.call(obj, "constructor") &&  
  152.                     !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {  
  153.                     return false;  
  154.                 }  
  155.             } catch ( e ) {  
  156.                 // IE8,9 Will throw exceptions on certain host objects #9897  
  157.                 return false;  
  158.             }  
  159.   
  160.             // Own properties are enumerated firstly, so to speed up,  
  161.             // if last one is own, then all properties are own.  
  162.   
  163.             var key;  
  164.             for ( key in obj ) {}  
  165.   
  166.             return key === undefined || core_hasOwn.call( obj, key );  
  167.         },  
  168.         isFunction : function(obj){  
  169.             if(obj && typeof obj == 'function'){  
  170.                 return true;  
  171.             }  
  172.             return false;  
  173.         },  
  174.         //onload事件实现  
  175.         ready : function(fn){  
  176.                 //如果是函数,加入到函数序列  
  177.                 if(fn && typeof fn == 'function' ){  
  178.                     jQuery.readyList.push(fn);  
  179.                 }  
  180.                 //文档加载完成,执行函数序列。  
  181.                 if(jQuery.isReady){  
  182.                     for(var i = 0;i < jQuery.readyList.length ;i++){  
  183.                         fn = jQuery.readyList[i];  
  184.                         jQuery.callback(fn);  
  185.                     }  
  186.                     return jQuery;  
  187.                 }  
  188.             },  
  189.         //回调  
  190.         callback : function(fn){  
  191.             fn.call(document,jQuery);  
  192.         }  
  193.     });  
  194.     //模拟实现jQuery的html方法  
  195.     jQuery.fn.extend({  
  196.     html : function(html){  
  197.         if(html && typeof html == 'string'){  
  198.            this.obj.innerHTML = html;  
  199.            return this;  
  200.         }  
  201.         return this.obj.innerHTML;  
  202.     }  
  203.     });  
  204.     //导出对象  
  205.     window.$ = window.jQuery = jQuery;  
  206.     //判断加载是否完成  
  207.     var top = false;  
  208.     try {  
  209.         top = window.frameElement == null && document.documentElement;  
  210.     } catch(e) {}  
  211.     if ( top && top.doScroll ) {  
  212.         (function doScrollCheck() {  
  213.             try {  
  214.                 top.doScroll("left");  
  215.                 jQuery.isReady = true;  
  216.                 jQuery.ready();  
  217.             } catch(e) {  
  218.                 setTimeout( doScrollCheck, 50 );  
  219.             }  
  220.         })();  
  221.     }  
  222. }(window));  

           下面这个是测试文件。

[html] view plain copy
  1. <html>  
  2. <head>  
  3. <script src="my-jquery-1.0.js" type="text/javascript"></script>  
  4. <script type="text/javascript">  
  5.     $.extend({  
  6.         testExtend:function(){  
  7.             alert('extend success');  
  8.         }  
  9.     });  
  10.     $.ready(function(){  
  11.         alert($("test").html());  
  12.         $.testExtend();  
  13.     });  
  14.     $.ready(function(){  
  15.         $("test").html("modify success");  
  16.     });  
  17.     $.ready(function(){  
  18.         alert($("test").html());  
  19.     });  
  20. </script>  
  21. </head>  
  22. <body>  
  23.     <div id="test">jquery src</div>  
  24. </body>  
  25. </html>  


           两个文件复制出来放在同一个文件夹下面,就可以看到效果。希望各位有不同意见的可以提出来一起探讨。

原文地址:http://blog.csdn.net/zuoxiaolong8810/article/details/8546527

原创粉丝点击