很久以前,我还在cnblogs里面逛的时候就提出过一个问题(刚找了半天没找到)。不知道大家有没有发现,用jQuery选择器"选择"之后的DOM上会添加jQuery*********属性。

< 
 DIV  
 id 
 =d1  
 jQuery1294122065250 
 ="1" 
 > 
 abc  
 </ 
 DIV 
 >



首先jQuery1294122065250中的"1294122065250"其实是一个时间戳。看看jQuery的源代码。


var 
  expando  
 = 
   
 " 
 jQuery 
 " 
   
 + 
  now(), uuid  
 = 
   
 0 
 , windowData  
 = 
  {};


由于使用了闭包,这样每一个jQuery对象都有一个expando属性。
属性值jQuery1294122065250="1"的"1"其实是jQuery的缓存的key。

首先了解一下jQuery缓存的相关API:

  • data(name):返回元素上储存的相应名字的数据
  • data(name,value):在元素上存放数据,同时也返回value。
  • jQuery.data(element,key,value):在元素上存放数据,返回jQuery对象。注意:这是一个底层方法。你应当使用.data()来代替。
  • jQuery.data([element],[key]): 查询在元素上存放的数据。如果不指定参数,则会返回元素上面存放的所有数据,以Object的形式返回。注意:这是一个底层方法。你应当使用.data()来代替。
  • removeData(data):移除元素上的缓存。

把jQuery.data方法是底层方法,data方法调用了该方法。要了解Query的缓存,最好的方法莫过于调试一下jQuery代码了。


< 
 script  
 type 
 ="text/javascript" 
 > 
 
     $( 
 function 
 (){
          
 var 
  $d1 
 = 
  $( 
 " 
 #d1 
 " 
 );
         $d1.data( 
 " 
 key 
 " 
 , 
 " 
 value 
 " 
 );
          
 var 
  v  
 = 
  $d1.data( 
 " 
 key 
 " 
 );

         $d1.click( 
 function 
 (){
             alert( 
 " 
 click 
 " 
 );
         });
          
 for 
  ( 
 var 
  k  
 in 
  jQuery.cache){
             alert(k 
 + 
 " 
 \n 
 " 
 + 
 jQuery.cache[k]);
         }
          
 debugger 
 ;
     });
 
 </ 
 script 
 > 
 
 
 < 
 div  
 id 
 ="d1" 
  class 
 ="" 
 > 
 
     abc
 
 </ 
 div 
 >



上面是一个简单的jQuery代码。在执行完$d1.data("key","value");后。经过调试后可以发现


jquery 后续增加的类 监听点击无效 jquery 添加点击事件监听_jquery


jQuery是一个全局变量:

// 
  Define a local copy of jQuery 
 
 
 var 
  jQuery  
 = 
   
 function 
 ( selector, context ) {
          
 // 
  The jQuery object is actually just the init constructor 'enhanced' 
 
 
          
 return 
   
 new 
  jQuery.fn.init( selector, context );
     },

      
 // 
  Map over jQuery in case of overwrite 
 
 
     _jQuery  
 = 
  window.jQuery,

      
 // 
  Map over the $ in case of overwrite 
 
 
     _$  
 = 
  window.$,


jQuery.data存放着所有的缓存key就是上面提到的DOM属性jQuery*********的值。


下面是读取缓存data函数的关键代码:


data:  
 function 
 ( elem, name, data ) {
          
 var 
  id  
 = 
  elem[ expando ], cache  
 = 
  jQuery.cache, thisCache;

         thisCache  
 = 
  cache[ id ];

          
 return 
   
 typeof 
  name  
 === 
   
 " 
 string 
 " 
   
 ? 
  thisCache[ name ] : thisCache;
     },



经过调试id 与jQuery********属性一致。直接通过jQuery.cache获取缓存值。



有缓存就必然会有清除缓存,不清除缓存意味着很有可能IE内存泄漏。


// 
  Prevent memory leaks in IE 
 
 // 
  Window isn't included so as not to unbind existing unload events 
 
 // 
  More info: 
 
 // 
   - http://isaacschlueter.com/2006/10/msie-memory-leaks/ 
 
 
 if 
  ( window.attachEvent  
 && 
   
 ! 
 window.addEventListener ) {
     window.attachEvent( 
 " 
 onunload 
 " 
 ,  
 function 
 () {
          
 for 
  (  
 var 
  id  
 in 
  jQuery.cache ) {
              
 if 
  ( jQuery.cache[ id ].handle ) {
                  
 // 
  Try/Catch is to handle iframes being unloaded, see #4280 
 
 
                  
 try 
  {
                     jQuery.event.remove( jQuery.cache[ id ].handle.elem );
                 }  
 catch 
 (e) {}
             }
         }
     });
 }

在window.unload时,jQuery将逐一删除jQuery.cache中的元素。



jQuery的事件绑定也利用了jQuery的缓存。上面的代码监听了#d1.click事件后,经过调试,可以发现,在缓存key为"events"上记录了监听的事件。


jquery 后续增加的类 监听点击无效 jquery 添加点击事件监听_function_02



通过上面的调试,发现所谓的事件监听或者绑定bind,其实就是在缓存中注册一下处理函数,当事件触发时,将DOM的注册的事件逐一执行就可以了。这其实是一种通用的事件处理机制,事件处理机制是一种典型的观察者设计模式。