jQuery 数据缓存模块进化史详细介绍

2020-05-19 07:29:05易采站长站整理

数据缓存系统最早应该是jQuery1.2引入的,那时它的事件系统完成照搬DE大神的addEvent.js,而addEvent在实现有个缺憾,它把事件的回调都放到EventTarget之上,这会引发循环引用,如果EventTarget是window对象,又会引发全局污染。有了数据缓存系统,除了规避这两个风险外,我们还可以有效地保存不同方法产生的中间变量,而这些变量会对另一个模块的方法有用,解耦方法间的依赖。对于jQuery来说,它的事件克隆乃至后来的列队实现都是离不开缓存系统。
jQuery1.2 在core模块新增了两个静态方法, data与removeData。data不用说,与jQuery其他方法一样,读写结合。jQuery的缓存系统是把所有数据都放$.cache之上,然后为每个要使用缓存系统的元素节点,文档对象与window对象分配一个UUID。UUID的属性名为一个随机的自定义属性,”jQuery” + (new Date()).getTime(), 值为整数,从零递增。但UUID总要附于一个对象上,如果那个对象是window,岂不是全局污染吗,因此jQuery内部判定它是window对象时,映射为一个叫windowData的空对象,然后UUID加在它之上。有了UUID,我们在首次访问缓存系统时,会在$.cache对象开辟一个空对象(缓存体),用于放置与目标对象有关的东西。这有点像银行开户了,UUID的值就是存折。removeData则会删掉不再需要保存数据,如果到最后,数据删清光了,它也没有任何键值对,成为空对象,jQuery就会从$.cache中删掉此对象,并从目标对象移除UUID。

//jQuery1.2.3
var expando = “jQuery” + (new Date()).getTime(), uuid = 0, windowData = {};
jQuery.extend({
cache: {},
data: function( elem, name, data ) {
elem = elem == window ? windowData : elem;//对window对象做特别处理
var id = elem[ expando ];
if ( !id ) //如果没有UUID则新设一个
id = elem[ expando ] = ++uuid;
//如果没有在$.cache中开户,则先开户
if ( name && !jQuery.cache[ id ] )
jQuery.cache[ id ] = {};
// 第三个参数不为undefined时,为写操作
if ( data != undefined )
jQuery.cache[ id ][ name ] = data;
//如果只有一个参数,则返回缓存对象,两个参数则返回目标数据
return name ? jQuery.cache[ id ][ name ] : id;
},
removeData: function( elem, name ) {
elem = elem == window ? windowData : elem;
var id = elem[ expando ];
if ( name ) {//移除目标数据
if ( jQuery.cache[ id ] ) {
delete jQuery.cache[ id ][ name ];
name = “”;
for ( name in jQuery.cache[ id ] )
break;
//遍历缓存体,如果不为空,那name会被改写,如果没有被改写,则!name 为true,
//从而引发再次调用此方法,但这次是只传一个参数,移除缓存体,
if ( !name )
jQuery.removeData( elem );
}
} else {
//移除UUID,但IE下对元素使用delete会抛错