学会读JQuery等JS插件源码

不少人以为jquery、ext等一些开源js源代码 十分的晦涩,读不懂,遇到问题须要调试也很费劲。其实我我的感受主要是有几个方面的缘由:javascript

一、对一些js不经常使用的语法、操做符不熟悉html

二、某个function中又嵌套了一些内部的function,使得整个代码的层次结构不像java代码那么清晰。java

三、js中容许变量先使用后定义,会形成咱们看代码时候突然冒出来一个变量、function,却找不到是在哪里定义的。jquery

 

那么今天给你们分享一下个人经验,扫清你的障碍。浏览器

1、一些晦涩的操做符:服务器

一、(function(){})();app

几乎全部的开源js代码开篇都是这样(function(……){……})(……);ide

下面是Jquery的部分源码:函数

Js代码
  1. (function( window, undefined ) { 
  2.     var jQuery = function( selector, context ) { 
  3.         // The jQuery object is actually just the init constructor 'enhanced' 
  4.         return new jQuery.fn.init( selector, context ); 
  5.     }, 
  6.  
  7.     // Map over jQuery in case of overwrite 
  8.     _jQuery = window.jQuery, 
  9.  
  10.     // Map over the $ in case of overwrite 
  11.     _$ = window.$, 
  12.     …… 
  13.     indexOf = Array.prototype.indexOf; 
  14.  
  15.     // Expose jQuery to the global object 
  16.     window.jQuery = window.$ = jQuery; 
  17. })(window); 

那么这个操做符(function(){})();究竟是什么意思呢?工具

(function(){})中的定义了一个function,紧接着的()表示当即执行这个function。

咱们看到Jquery源码第一个()中是定义了一个匿名function( window, undefined ) {};接着末尾有个(window),就表示执行这个匿名function,并传入参数window

 

在匿名function( window, undefined ) {}中,定义了一个局部变量jQuery;而后在末尾咱们看到Jquery末尾有一句window.jQuery = window.$ = jQuery; 这句代码就表示,将此前定义的jQuery导出到window对象 。这也是为何咱们能够在代码任何地方直接使用$、jQuery对象,由于在这里已经将$、jQuery对象挂载到window下去了,而window.$、window.jQuery与直接使用$、jQuery是没有区别的。

(注意,这个window对象是传入的参数window,而不是浏览器window对象!!一个形参、一个实参。咱们能够在定义function的时候,将参数window取名为其余字符。因此咱们看到jquery.min.js中这个匿名function变成了(function(E,B){})(window);)

 

一般(function(){})()用来封装一些私有成员或者公共成员的导出。

 

二、使人迷惑的","

咱们知道“,”通常用于一次定义多个变量、定义多个参数等。像上面的jQuery源码中在var jQuery后面,使用“,”一次定义了不少个变量。

可是,像下面的代码,可能你们就不必定看得懂了:

Js代码
  1. //html:<input type="hidden" value="king" id="nameHide"/> 
  2. jQuery(document).ready(function() { 
  3.     var showName=function(){ 
  4.         var value,nameInput=$("#nameHide"); 
  5.         return nameInput.show(),value=nameInput.val(); 
  6.     }; 
  7.     alert(showName()); 
  8. }); 
  9. //结果:弹出king 

这里的“nameInput.show(),value=nameInput.val()”中的“,”运算符的做用是返回","右侧表达式的值。因此,return 后面若是有多个表达式,且表达式之间由","隔开,整个return表达式返回的是最后一个","右侧的表达式的值。

 

“,”在开源代码中经常被用于return表达式中,以及跟下面咱们要讲到的"()"运算符一块儿使用。

 

三、“()”广义上的代码包装

咱们遇到复杂的逻辑表达式时,咱们一般会把须要一块儿运算的表达式用“()”包起来:(a||b)&&(c||d)

其实,咱们能够这样理解:"()"运算符将一个表达式包裹起来做为一个总体进行运算,而后返回这个总体的值。

那么上面的(function(){})()中左侧定义function的()也是这个做用,将这个function给包裹起来,而后返回这个function。咱们调用方法通常是a();那么(function(){})的做用就是返回这个function对象,而后(function(){})()右侧的()表示调用这个function。

 

咱们再来看其余的用法:

Js代码
  1. //html:<input value="kings" id="name"/><div id="nameErrorTip">输入错误!</div> 
  2. jQuery(document).ready(function() { 
  3.     var nameValidate=function(){ 
  4.         var value,nameInput=$("#name"),nameErrorTip=$("#nameErrorTip");  
  5.         return (value=nameInput.val(),value=="king")?(nameErrorTip.hide(),"对了,输入为king!"):(nameErrorTip.show(),"请输入king!"); 
  6.     }; 
  7.     alert(nameValidate()); 
  8. }); 
  9.  
  10. //结果 nameErrorTip显示,弹出"请输入king!" 
  11.  
  12.  
  13.  
  14. //html:<input value="king" id="name"/><div id="nameErrorTip">输入错误!</div> 
  15. //结果 nameErrorTip隐藏,弹出"对了,输入为king!" 

这里“ (value=nameInput.val(),value=="king")”中"()"将里面的表达式做为一个总体进行运算,而里面的表达式又是由","构成的多个表达式组,因此执行的时候会把这多个表达式都执行一次 ,而且返回最后一个表达式的值!

因此 (value=nameInput.val(),value=="king")执行时,先运算value的值,再判断是否为"king"。若是为king,会执行(nameErrorTip.hide(),"对了,输入为king!")。这个表达式又先将nameErrorTip隐藏,再返回一个"对了,输入为king!"字符串做为 整个return的值。

 

四、||、&&、if()逻辑让人头晕

 

||、&&两侧参与运算的是逻辑表达式,if()中也是。可是咱们在不少开源代码中看到的||、&&参与运算的表达式看起来却好像不是逻辑表达式……

 

下面节选一段jQuery.tool中的一段源码:

Js代码
  1. e.circular || (f.onBeforeSeek(function(a, b) { 
  2.                     setTimeout(function() { 
  3.                                 a.isDefaultPrevented() 
  4.                                         || (n.toggleClass(e.disabledClass, 
  5.                                                 b <= 0), o.toggleClass( 
  6.                                                 e.disabledClass, b >= f 
  7.                                                         .getSize() 
  8.                                                         - 1)) 
  9.                             }, 1) 
  10.                 }), e.initialIndex || n.addClass(e.disabledClass)), f.getSize() < 2 
  11.                 && n.add(o).addClass(e.disabledClass), e.mousewheel 
  12.                 && a.fn.mousewheel && b.mousewheel(function(a, b) { 
  13.                             if (e.mousewheel) { 
  14.                                 f.move(b < 0 ? 1 : -1, e.wheelSpeed || 50); 
  15.                                 return !1 
  16.                             } 
  17.                         }); 

这里有多处||、&&。但与运算的表达式倒是调用某个函数的返回值。

 

其实,js中的逻辑表达式是按照真值、假值来分的。true是真值;1是真值;一个对象也是真值;false是假值;""、0是假值。

 

在js中&&、||不必定都是用来判断一个表达式的逻辑值是true、false,更多的是用来依据真值或者假值执行相应操做!

 

咱们知道,||运算的时候,会先运算左侧的表达式的值,若是为真值,那么真个表达式就为真值,而同时右侧表达式是真值、假值都不重要,由于右侧表达式都再也不继续参与运算了。又若是左侧为假值,则继续运算右侧表达式。

&&则先运算左侧表达式,两侧表达式,一个为假值,则整个表达式为假值。

 

这里关键是这个真值或者假值的运算过程当中,咱们可使用上面介绍的","、"()"将一组表达式串起来执行。也就是说,这个表达式可能会很长很长,我甚至能够定义一个function在里面。这些表达式在执行过程当中,有能够进行某些附加操做。好比咱们但愿这个表达式为真值的时候咱们作什么,假值的时候作什么,把这些操做用"()"、","串起来做为一个总体运算。

因而就有了上面的复杂代码。

 

咱们来看个实例吧。是上面例子的升级版。咱们加入一个nameInput是否存在的判断:

Js代码
  1. jQuery(document).ready(function() { 
  2.     var nameValidate=function(){ 
  3.         var value,nameInput=$("#name"),nameErrorTip=$("#nameErrorTip"),msg; 
  4.         msg=(value=nameInput.val(),value=="king")?(nameErrorTip.hide(),"对了,输入为king!"):(nameErrorTip.show(),"请输入king!"); 
  5.         return (nameInput.length&&nameInput.val()&&nameErrorTip.length&&msg)||"没有找到name输入框或者输入框没有值!"; 
  6.     }; 
  7.     alert(nameValidate()); 
  8. }); 

测试:

Js代码
  1. //html:<input value="king" id="myName"/> 
  2. //结果:弹出“没有找到name输入框或者输入框没有值!” 
  3.  
  4. //<input value="king" id="name"/><div id="nameErrorTip">输入错误!</div> 
  5. //结果:弹出“对了,输入为king!”,nameErrorTip被隐藏 

return表示中 nameInput.length&&nameInput.val()&&nameErrorTip.length&&msg会先运算 nameInput.length的值,若是length为0则表达式为假值,若是为1则为真值。val()操做也是如此,若是val()结果为""则表达式也是假值。几个表达式之间为&&运算,则表示依次运算几个表达式的值,若是都未真值则返回最后一个表达式的值 ,因为整个表达式与

"没有找到name输入框或者输入框没有值!"

表达式之间是||运算,因此前面的表达式其中一个表达式为假值则返回||右侧的表达式的值,也就是整个“没有找到name输入框或者输入框没有值!”字符串。

 

这个javascript为何要搞这些晦涩的运算符呢?

由于javascript一般在客户端运行,那么从服务器端将js代码传输到客户端确定须要耗时。上面的这些运算符都是为了减小代码量。再加上使用压缩工具去掉空格,替换变量名,就可使用压缩率达到最好。

相关文章
相关标签/搜索