jQuery 源码分析笔记(6) jQuery.data


Posted in Javascript onJune 08, 2011

data部分的代码从1381行开始。最开始的几行关键代码:

jQuery.extend({ 
// 存储数据的地方,关键实现核心 
cache: { }, 
// 分配ID用的seed 
uuid: 0, 
// 为了区别不同的jQuery实例存储的数据,使用前缀+jQuery版本号+随机数作为Key 
expando: "jQuery" + (jQuery.fn.jquery + Math.random()).replace(/\D/g, ""), 
// 以下元素没有Data:embed和applet(这玩意还活着么),除了Flash之外的object。 
noData: { 
"embed": true, 
"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", 
"applet": true 
} 
});

对外的接口都调用了两个内部函数:jQuery.data(elem, name, data, pvt)和jQuery.removeData(elem, name, pvt)。而removeData的逻辑与data类似,只是data是加入数据,而removeData使用delete或者设置为null删除数据。
data部分的代码中明确区分了JS对象和DOM对象的保存,这是为了解决部分浏览器的内存泄漏问题。在低版本IE中,当DOM和JS对象之间出现循环引用时,GC就无法正确处理。参见Understanding and Solving Internet Explorer Leak Patterns。至于COM对象,因为已经限制object元素没有data,就绕过了这个问题。
data: function(elem, name, data, pvt) { 
// 如果属于noData中定义的元素 
if(!jQuery.acceptData(elem)) { 
return; 
} 
var internalKey = jQuery.expando, 
getByName = typeof name === "string", 
thisCache, 
isNode = elem.nodeType, 
// DOM元素需要保存在Cache,JS对象直接保存到elem 
cache = isNode ? jQuery.cache : elem, 
// 如果elem的jQuery.expando已经有值了,就重用 
id = isNode ? elem[jQuery.expando] : elem[jQuery.expando] && jQuery.expando; 
<PRE class=brush:;gutter:true;><CODE>// data未定义,说明当前调用是查询数据,但是对象没有任何数据,直接返回 
if((!id || (pvt && id && !cache[id][internalKey])) && getByName && data === undefined) { 
return; 
} 
if(!id) { 
if(isNode) { 
// 用uuid种子递增分配唯一ID,只有DOM元素需要。因为需要存在全局cache中 
elem[jQuery.expando] = id = ++jQuery.uuid; 
} else { 
id = jQuery.expando; 
} 
} 
// 清空原来的值 
if(!cache[id]) { 
cache[id] = {}; 
if(!isNode) { 
cache[id].toJSON = jQuery.noop; 
} 
} 
// 用extend扩展cache,增加一个属性,用来保存数据 
if(typeof name === "object" || typeof name === "function") { 
if(pvt) { 
cache[id][internalKey] = jQuery.expand(cache[id][internalKey], name); 
} else { 
cache[id] = jQuery.extend(cache[id], name); 
} 
} 
thisCache = cahce[id]; 
// 避免Key冲突 
if(pvt) { 
if(!thisCache[internalKey]) { 
thisCahce[internalKey] = {}; 
} 
thisCache = thisCache[internalKey]; 
} 
if(data !== undefined) { 
thisCache[jQuery.camelCase(name)] = data; 
} 
return getByName ? thisCache[jQuery.camelCase(name)] : thisCache; 
} 
removeData: function( elem, name, pvt ) { // 前面部分与data类似 // ... // 部分浏览器不支持在Element上进行delete操作,在jQuery.support中检查过这个浏览器特性。 // 如果delete失败的话,就先设置成null。 if ( jQuery.support.deleteExpando || cache != window ) { delete cache[ id ]; } else { cache[ id ] = null; } 
<PRE class=brush:;gutter:true;><CODE>var internalCache = cache[ id ][ internalKey ]; 
// 如果还有数据,就清空一次再设置,增加性能 
if ( internalCache ) { 
cache[ id ] = {}; 
cache[ id ][ internalKey ] = internalCache; 
// 已经没有任何数据了,就全部删除 
} else if ( isNode ) { 
// 如果支持delete,就删除。 
// IE使用removeAttribute,所以尝试一次。再失败就只能设置为null了。 
if ( jQuery.support.deleteExpando ) { 
delete elem[ jQuery.expando ]; 
} else if ( elem.removeAttribute ) { 
elem.removeAttribute( jQuery.expando ); 
} else { 
elem[ jQuery.expando ] = null; 
} 
} 
}
Javascript 相关文章推荐
Javascript 入门基础学习
Mar 10 Javascript
js操作textarea方法集合封装(兼容IE,firefox)
Feb 22 Javascript
JS显示表格内指定行html代码的方法
Mar 31 Javascript
12行javascript代码绘制一个八卦图
Apr 02 Javascript
JS实现方向键切换输入框焦点的方法
Aug 19 Javascript
JavaScript中push(),join() 函数 实例详解
Sep 06 Javascript
对javascript继承的理解
Oct 11 Javascript
简单的jQuery拖拽排序效果的实现(增强动态)
Feb 09 Javascript
C#实现将一个字符转换为整数
Dec 12 Javascript
在vue中使用express-mock搭建mock服务的方法
Nov 07 Javascript
jquery的$().each和$.each的区别
Jan 18 jQuery
jQuery实现简单QQ聊天框
Aug 27 jQuery
jQuery中的.bind()、.live()和.delegate()之间区别分析
Jun 08 #Javascript
jquery 跨域访问问题解决方法(笔记)
Jun 08 #Javascript
精通Javascript系列之数据类型 字符串
Jun 08 #Javascript
精通Javascript系列之Javascript基础篇
Jun 07 #Javascript
精通Javascript系列之数值计算
Jun 07 #Javascript
jQuery 源码分析笔记(4) Ready函数
Jun 02 #Javascript
在IE 浏览器中使用 jquery的fadeIn() 效果 英文字符字体加粗
Jun 02 #Javascript
You might like
用PHP实现将GB编码转换为UTF8
2006/11/25 PHP
Adodb的十个实例(清晰版)
2006/12/31 PHP
关于PHP实现异步操作的研究
2013/02/03 PHP
PHP中spl_autoload_register()和__autoload()区别分析
2014/05/10 PHP
php foreach正序倒序输出示例代码
2014/07/01 PHP
php中namespace use用法实例分析
2016/01/22 PHP
php使用正则表达式获取字符串中的URL
2016/12/29 PHP
PHP正则之正向预查与反向预查讲解与实例
2020/04/06 PHP
NodeJS中Buffer模块详解
2015/01/07 NodeJs
JS获取鼠标坐标位置实例分析
2016/01/20 Javascript
基于AngularJS前端云组件最佳实践
2016/10/20 Javascript
js 将input框中的输入自动转化成半角大写(税号输入框)
2017/02/16 Javascript
Angular.js中ng-include用法及多标签页面的实现方式详解
2017/05/07 Javascript
优雅的在React项目中使用Redux的方法
2018/11/10 Javascript
基于vue开发微信小程序mpvue-docs跳转页面功能
2019/04/10 Javascript
原生js代码能实现call和bind吗
2019/07/31 Javascript
JS阻止事件冒泡的方法详解
2019/08/26 Javascript
使用js实现单链解决前端队列问题的方法
2020/02/03 Javascript
es6数组includes()用法实例分析
2020/04/18 Javascript
VUE+elementui组件在table-cell单元格中绘制微型echarts图
2020/04/20 Javascript
基于 Vue 的 Electron 项目搭建过程图文详解
2020/07/22 Javascript
Python中的defaultdict与__missing__()使用介绍
2018/02/03 Python
python集合比较(交集,并集,差集)方法详解
2018/09/13 Python
pycharm的console输入实现换行的方法
2019/01/16 Python
Python项目跨域问题解决方案
2020/06/22 Python
python3代码输出嵌套式对象实例详解
2020/12/03 Python
使用Python封装excel操作指南
2021/01/29 Python
澳大利亚制造的羊皮靴:Original UGG Boots
2017/11/13 全球购物
医院护理人员的自我评价分享
2013/10/04 职场文书
体育教师个人的自我评价
2014/02/16 职场文书
学校爱心捐款倡议书
2014/05/13 职场文书
计算机应用应届生求职信
2014/07/12 职场文书
2015年助残日活动总结
2015/03/27 职场文书
董事长致辞
2015/07/29 职场文书
Vue全家桶入门基础教程
2021/05/14 Vue.js
Redis Stream类型的使用详解
2021/11/11 Redis