打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
躺在jquery的石榴裙下 之 jQuery.fn.init
认识第一个比较重要的方法jQuery.fn.init
源码如下:
Java代码  
  1. selector = selector || document;  
  2. if ( selector.nodeType ) {  
  3.     this[0] = selector;  
  4.     this.length = 1;  
  5.     return this;  
  6. }  


selector = selector || document 暗示了如果$(),那么就相当于$(document)

selector.nodeType用来判断是否是一个domElement对象,如果是直接将本对象包装成jquery对象返回,这里要说明一点,实际jquery对象是一个伪数组或者说是一个功能异常强大的集合,你可以通过下标去访问里面的元素和length属性,但它不会像数组一样去帮你维护里面的元素,比如你将length设为空,它不会帮你将里面的元素清空,因为他是一个伪造的。

Java代码  
  1. if ( typeof selector == "string" ) {  
  2.      ....  
  3. }else if ( jQuery.isFunction( selector ) )  
  4.     return jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );  
  5.   
  6. return this.setArray(jQuery.makeArray(selector));  

判断是否是字符串,情况比较多,稍后讨论,先看简单的,好像也不太简单
jQuery.isFunction( selector ) 判断传进来的是否是一个函数
isFunction函数体如下:
Java代码  
  1. return !!fn && typeof fn != "string" && !fn.nodeName &&  
  2.     fn.constructor != Array && /^[\s[]?function/.test( fn + "" );  

!!fn强制返回boolean型,然后否定了它不是字符串,不是dom元素,不是数组,然后用一个正则进行验证,为什么要加个"^[\s[]?"让我很困惑,因为这是一个全局函数所以才判断这么多,实际上就这个逻辑关系,只用最后一个验证就行了,因为前面已经都有对应的判断了,不过这个方法还是相当具有价值的,多多品味

jQuery( document )返回是一个骨子里是document的jquery对象
[ jQuery.fn.ready ? "ready" : "load" ]如果jQuery.fn存在ready属性,返回[ready]否则返回[load],这种写法很值得借鉴,简洁高效

下面找寻load,ready方法
load : (约2420) 牵涉事件,暂时搁置一下
ready : (约2282)
Java代码  
  1. jQuery.fn.ready: function(fn) {  
  2.     bindReady(); //关于事件暂时不讨论  
  3.     if (jQuery.isReady)  
  4.         fn.call(document, jQuery);   
  5.     else  
  6.         jQuery.readyList.push(function() {   
  7.                        return fn.call(this, jQuery);   
  8.                   });   
  9.     return this;  
  10. }  
jquery有一套快速的检查文档是否加载完毕的例子,这个要比传统的window.onload要快,他的实现是通过一个计时器,不停的检查,知道加载好后将jQuery.isReady属性等于true
,所以上面这段代码意思就是,如果没有加载好就将其放入readyList数组中,当前的this指向调用ready的jquery对象(即$(document)),而且这个函数还被注入了jQuery参数,所以想查看readyList里面的个数 $(function(j){alert(j.readyList.length)}),如果dom已经加载好,就会直接执行

当dom从未加载好到加载好后,会调用全局的jQuery.ready(约2304),将isReady改为true,然后遍历readyList数组,执行里面的方法,一定要把最后页面执行$()里面function这个过程想通

下一个return this.setArray(jQuery.makeArray(selector));
Java代码  
  1. setArray: function(elems) {  
  2.     this.length = 0;  
  3.     Array.prototype.push.apply(this, elems);   
  4.   
  5.     return this;  
  6. }  
因为是伪数组,所以记住在改变数组时要自己维护length,剩下就不解释了,属于借鸡生蛋的做法

Java代码  
  1. makeArray: function(array) {  
  2.     var ret = [];   
  3.     if (array != null) {  
  4.         var i = array.length;  
  5.         if (i == null || array.split || array.setInterval || array.call)  
  6.             ret[0] = array;  
  7.         else  
  8.             while (i)  
  9.             ret[--i] = array[i];  
  10.     }   
  11.     return ret;  
  12. }  
注意有length属性不仅仅是array,还有arguments,function,伪数组(例如jquery对象),window。i == null主要是针对没有length属性的,比如object,12,true这样的基本类型,这函数的意义就是无论什么将它构造成一个数组。作者之所以分成两个方法,是考虑到粒度的问题,这种粒度对后面的重用会大有帮组


最麻烦的:if ( typeof selector == "string" )这块
首先来看看我们已经分析了那些还剩下那些情况:

1.if ( selector.nodeType ) 处理了dom对象
2.if (jQuery.isFunction(selector)) 处理预加载函数这一块
3.this.setArray(jQuery.makeArray(selector)) 处理了数组和伪数组情况

api中提供的方法,属于字符串的一块
1) 处理选择器,如  #id,.class,:input 之类的
2) 直接构建dom,$("<div><p>Hello</p></div>")

init方法上有两个参数selector, context其中context就是规定它的寻找范围,主要是处于性能上的考虑,假设已经了解dom的结构,可以加快锁定元素的速度,默认为document

Java代码  
  1. var match = quickExpr.exec(selector);   
  2. if (match && (match[1] || !context)) {   
  3.     if (match[1])  
  4.         selector = jQuery.clean([match[1]], context);   
  5.     else {  
  6.         var elem = document.getElementById(match[3]);   
  7.         if (elem) {  
  8.             if (elem.id != match[3])  
  9.                 return jQuery().find(selector);   
  10.             return jQuery(elem);  
  11.         }  
  12.         selector = [];  
  13.     }   
  14. else  
  15.     return jQuery(context).find(selector);   


quickExpr : "/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/"只关注两种情况,一种是直接针对构建dom的,一种是针对id选择器的,特别对id照顾是因为getElementById的速度是最快的,之所以会多出if (elem.id != match[3])这种情况是因为我们的ie老大哥在解析input这类的标签时在没有id有name的时候,会将name取代id,对于这种擅作主张的行为很不能接受,所要小心了。

jQuery.clean([match[1]], context) : 方法实现是创建一个临时的div,然后将
<(.|\s)+>添加到这个div的innerHTML上,会自动生成dom对象,然后解析这个对象,打包成数组返回。后面会详细说明

如果没有匹配结果或存在context的情况下,将执行jQuery(context).find(selector)方法通过选择器来寻找结果,这个选择器一块的知识后面会提到
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
$到底是什么
传智播客1-3
JavaScript面试
提升jQuery性能的十个技巧
jQuery核心源码core.js分析
jQuery数据类型
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服