jQuery data

一个简单的Cache

复制代码
(function(){var __cache = {},Cache = {get: function(__name){return __cache[__name] || undefined;},    set: function(__name, __value){return (__cache[__name] = __value)}};this.Cache = Cache;
})();alert(Cache.get("name"));    //undefined
Cache.set("name", "Bob");
alert(Cache.get("name"));    //Bob
复制代码

 

但这不是jQuery想要的

jQuery要解决的是对应元素的缓存数据。

例如,我们用document.getElementById获得了一个元素element,然后有一个对应的参数value的属性名是key,那么我们想保存到缓存里,那么我们需要告诉缓存element、key、value才能保存数据,而想要获得这个值,则要告诉缓存element和key,才能得到value。

所以jQuery的缓存实际上是直接绑定到对象中的。

为什么?因为这样简单啊。

用上面的方法,先要将element转成字符串或者数字对应缓存里的对象,然后再用该对象来缓存不同key的value……这……太……麻……烦……了!!

实际上,由于Javascript没有Hash值方法,所以对象转字符串或数字并没有太好的方法,当然绑一个ID在元素上除外。

 

做一个别人一般不会用的令牌

但是绑定在对象上有一个问题,如果属性名用什么呢?

如果这个属性名别人也拿去用就悲剧了,比如我用.cache绑定数据,但是另一个库也有.cache来绑定数据,就……

所以,jQuery做了一个正常情况下别人不会用的令牌。

jQuery.expando = "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" );

replace函数将core_verision中的非数字全部替换掉,所以最后这个令牌是一个jQuery后面加一个随机数,比如:

  jQuery20018518865841457738

 

jQuery.hasData

jQuery.hasData = function( elem ) {elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];return !!elem && !isEmptyDataObject( elem );
};

从这个函数可以看出,如果elem是DOM Element对象,则数据存在jQuery.cahe中,否则存在存在elem对象中。

 

jQuery.data & jQuery.removeData

jQuery.data = function( elem, name, data ) {return internalData( elem, name, data, false );
};
jQuery.removeData = function( elem, name ) {return internalRemoveData( elem, name, false );
};

他们分别调用了internalData和internalRemoveData。

注意专用接口jQuery._data和jQuery._removeData传的最后一个值有些不同。

这个后面会说到。

jQuery._data = function( elem, name, data ) {return internalData( elem, name, data, true );
};
jQuery._removeData = function( elem, name ) {return internalRemoveData( elem, name, true );
};

 

internalData

复制代码
function internalData( elem, name, data, pvt /* Internal Use Only */ ){// 判断该对象能不能绑定数据if ( !jQuery.acceptData( elem ) ) {return;}var thisCache, ret,internalKey = jQuery.expando,getByName = typeof name === "string",// 由于IE6-7的DOM节点引用的垃圾回收问题,需要分开处理DOM节点和JS对象// 真心想吐槽,这不是jQuery 2.0么!!!不是说不支持IE6-8么!!!isNode = elem.nodeType,// 如果是DOM节点,则使用jQuery.cache存储数据,否则使用elem本身cache = isNode ? jQuery.cache : elem,// 得到对象的ID号,如果是DOM节点则是其以令牌为属性名的属性值,否则是令牌id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;// 避免为了从一个根本没有数据的对象获取数据而浪费时间if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {return;}// 如果没有IDif ( !id ) {// 如果是DOM节点,就给他一个IDif ( isNode ) {elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;// 否则以令牌作为其ID} else {id = internalKey;}}// 如果对应ID的缓存不存在if ( !cache[ id ] ) {// 初始化缓存cache[ id ] = {};// 避免对JS对象使用JSON.stringify时暴露jQuery的元数据对象,所以给对象添加toJSON方法if ( !isNode ) {cache[ id ].toJSON = jQuery.noop;}}// 如果name是对象或者函数if ( typeof name === "object" || typeof name === "function" ) {// 如果是jQuery内部私用数据if ( pvt ) {// 则将数据保存在指定ID的对应缓存中cache[ id ] = jQuery.extend( cache[ id ], name );} else {//否则保存在指定ID对应缓存的data属性中cache[ id ].data = jQuery.extend( cache[ id ].data, name );}}//定位缓存中的数据thisCache = cache[ id ];// 区分内部私用以及公用来避免内部数据和用户定义数据的key重复导致的互相覆盖// 还有一个有趣的问题,为什么用户数据在data中,而内部数据直接在缓存对象里,而不是反过来呢?// 如果不是内部私用if ( !pvt ) {// 如果缓存中没有data属性,则初始化一个if ( !thisCache.data ) {thisCache.data = {};}// 定位缓存位置thisCache = thisCache.data;}// 如果data已定义,则是写入操作,写入数据if ( data !== undefined ) {thisCache[ jQuery.camelCase( name ) ] = data;}// 如果name是字符串,即通过字符串来获取数据if ( getByName ) {// 首先通过name来获取ret = thisCache[ name ];// 看看上面方法有没有得到数据if ( ret == null ) {// 如果没有,则用驼峰式name来获取ret = thisCache[ jQuery.camelCase( name ) ];}} else {// 不是则直接将数据传出ret = thisCache;}return ret;
}
复制代码

jQuery 2.0中data的实现依然同1.9版本差不多,当然这也不一定是IE6-7的原因才将DOM节点和JS对象分开处理的,我们知道JS引擎读取DOM数据的过程是较为费时费力的,从这个角度来看,将DOM节点的缓存设计在全局会是个比较快的方案。

这里还有两个有趣的问题:

  1. 如果传进去的data是函数,那么到底缓存了什么?
  2. 为什么用户数据在data中,而内部数据直接在缓存对象里,而不是反过来呢?

 

internalRemoveData

复制代码
function internalRemoveData( elem, name, pvt /* For internal use only */ ){// 判断该对象能不能绑定数据if ( !jQuery.acceptData( elem ) ) {return;}var thisCache, i, l,isNode = elem.nodeType,cache = isNode ? jQuery.cache : elem,id = isNode ? elem[ jQuery.expando ] : jQuery.expando;// 如果缓存对象根本不存在,那么就不用删除了if ( !cache[ id ] ) {return;}// 如果name存在if ( name ) {// 定位缓存位置thisCache = pvt ? cache[ id ] : cache[ id ].data;// 如果缓存存在if ( thisCache ) {// 支持以空格分隔的字符串if ( !jQuery.isArray( name ) ) {// try the string as a key before any manipulation// 看看字符串name存不存在if ( name in thisCache ) {// 定位要删除的缓存name = [ name ];// 不存在证明传进来的是以空格分隔的字符串或者需要转成驼峰写法} else {//转成驼峰写法name = jQuery.camelCase( name );//看看现在对不对if ( name in thisCache ) {name = [ name ];//不对证明是以空格分隔的字符串} else {//以空格分隔字符串name = name.split(" ");}}} else {// 如果是数组,则预处理name = name.concat( jQuery.map( name, jQuery.camelCase ) );}// 遍历删除for ( i = 0, l = name.length; i < l; i++ ) {delete thisCache[ name[i] ];}// 如果缓存非空,则退出,证明缓存如果都空了,就要删掉它if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {return;}}}// 如果不是私有的if ( !pvt ) {// 删除data属性delete cache[ id ].data;// 如果缓存对象并非空的,证明可能还有些私有属性存储了,退出if ( !isEmptyDataObject( cache[ id ] ) ) {return;}}// 到这里已经所有缓存数据都没有了,可以清理ID之类的东西了// 如果是DOM节点if ( isNode ) {// 清理数据jQuery.cleanData( [ elem ], true );// 看看能不能用delete方法删除// 还要判断cache本身是不是window对象,否则会抛错} else if ( jQuery.support.deleteExpando || cache != cache.window ) {delete cache[ id ];// 如果不能删除则设为null} else {cache[ id ] = null;}
}
复制代码

 

jQuery.fn.data

复制代码
jQuery.fn.data = function( key, value ) {var attrs, name,elem = this[0],i = 0,data = null;// 如果key没有被定义,即要得到所有数据if ( key === undefined ) {// 如果长度不为0if ( this.length ) {// 用jQuery.data获取第一个元素的数据data = jQuery.data( elem );// 如果元素是节点,对应的内部数据parsedAttrs不存在if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {// 从attrubutes中获取数据attrs = elem.attributes;// 遍历for ( ; i < attrs.length; i++ ) {name = attrs[i].name;// 看看属性名是不是data-xxx,就是要支持HTML5 data-Attributesif ( !name.indexOf( "data-" ) ) {// 是则数据名为data-后面的字符串name = jQuery.camelCase( name.slice(5) );// 数据值通过daataAttr获取dataAttr( elem, name, data[ name ] );}}// 保存到对应内部缓存parsedAttrs中jQuery._data( elem, "parsedAttrs", true );}}return data;}// 如果key是对象,则通过jQuery.data设置多个属性if ( typeof key === "object" ) {return this.each(function() {jQuery.data( this, key );});}// 否则用access操作链式或不用链式return jQuery.access( this, function( value ) {// 如果value没有定义,则是读取操作if ( value === undefined ) {// 如果有第一个元素,则返回对应的数据,否则为空return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;}// 设置操作调用jQuery.data来赋值this.each(function() {jQuery.data( this, key, value );});}, null, value, arguments.length > 1, null, true );
};
复制代码

这个方法主要是支持了HTML5 data-Attributes。

我们可以发现,实际上jQuery最终也把data-Attributes数据也保存到缓存中,这样是为了不再DOM和JS引擎中频繁读取。

 

jQuery.fn.removeData

jQuery.fn.removeData = function( key ) {return this.each(function() {jQuery.removeData( this, key );});
}

这个就很简单法了,只是遍历所有元素使用removeData而已。

 

dataAttr

复制代码
function dataAttr( elem, key, data ) {// 从data-*获取数据if ( data === undefined && elem.nodeType === 1 ) {// 预处理name,将驼峰式替换成data-*-*形式var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();// 尝试获取该attribute的数据data = elem.getAttribute( name );// 如果数据是字符串if ( typeof data === "string" ) {try {// 如果数据是"true",则为truedata = data === "true" ? true :// 如果数据是"false",则为falsedata === "false" ? false :// 如果数据时"null",则为nulldata === "null" ? null :// 将字符串转成数字,再转成字符串看看有没有改变,没改变则证明是数字+data + "" === data ? +data :// 否则测试数据是否是以{}包裹,是则尝试转成对象rbrace.test( data ) ? jQuery.parseJSON( data ) ://否则就当它是普通字符串data;} catch( e ) {}//保存数据jQuery.data( elem, key, data );// 否则数据未定义} else {data = undefined;}}return data;
}

转载于:https://www.cnblogs.com/chouji717/p/6109187.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356453.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式(中介者模式-对象去耦)

声明&#xff1a;本系列文章内容摘自《iOS设计模式》 中介者模式 用一个对象来封装一系列对象的交互方式。中介者使个对象不需要显式地相互调用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互。 何时使用中介者模式 1.对象间的交互虽定义明确然而非…

windows服务器的DDOS防御,

抵御 SYN 攻击 SYN 攻击利用了 TCP/IP 连接建立机制中的安全漏洞。要实施 SYN 洪水攻击&#xff0c;攻击者会使用程序发送大量 TCP SYN 请求来填满服务器上的挂起连接队列。这会禁止其他用户建立网络连接。 要保护网络抵御 SYN 攻击&#xff0c;请按照下面这些通用步骤操作&…

java程序运行结果题_2016年关于Java编程与程序运行结果笔试题

2016年关于Java编程与程序运行结果笔试题1.Java编程,打印昨天的当前时刻public class YesterdayCurrent{public void main(String[] args){Calendar cal Calendar.getInstance();cal.add(Calendar.DATE, -1);System.out.println(cal.getTime());}}2.文件读写,实现一个计数器pu…

Hystrix简介– Hello World

在先前的博客文章中&#xff0c;我谈到了需要像Netflix Hystrix这样的库的动机。 在这里&#xff0c;我将跳入一些非常基本的方法来开始使用Hystrix&#xff0c;并在更复杂的用例中进行后续介绍。 你好&#xff0c;世界 以下是“ Hystrix命令”的一个简单的Hello World示例&am…

js base64编码 java 解码_JavaScript字符串的Base64编码与解码

有时文本里包含一些不可打印的符号&#xff0c;而你需要把它们传输到服务器&#xff0c;这时我们会需要用到Base64编码。或者你需要把一个图片内容以文本格式嵌入到网页中&#xff0c;这时你也会用到 Base64 编码。所谓 Base64 是一种基于64个可打印字符来表示二进制数据的方法…

ssh图片上传 java_ssh上传并显示图片

struts部分&#xff1a;attribute"upfileForm"input"/upload/uploadfile.jsp"name"upfileForm"path"/upfile"scope"request"validate"true"type"com.yourcompany.struts.action.UpfileAction">publi…

责任链设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01; 目录 …

使用JUnit规则进行干净的集成测试

JUnit Rules的优势&#xff0c;尤其是在进行集成测试时&#xff0c;几乎不能被高估。 在本文中&#xff0c;我们将阐明ExternalResource扩展的有用性。 在我们必须使用抽象外部资源的第三方库的情况下&#xff0c;这些简化了灯具控制。 作为示例&#xff0c;我们将看看如何基于…

winform基础窗体设置及基础控件

WinForm - 也叫做C/S 客户端 另&#xff1a;B/S是 网页端 客户端应用程序 - 是需要安装在用户电脑上才可以使用的程序 特点&#xff1a; 不需要联网也可以打开使用部分功能&#xff0c;但是现在的情况是许多功能依然需要互联网的支持&#xff0c;代码部分在用户电脑上执行 使用…

【FastJSON】解决FastJson中“$ref 循环引用”的问题

0、开发环境 SSH&#xff0c;EasyUI&#xff0c;MySQL 1、需求要求&#xff1a; (1)首先获取所有的贷款订单数据&#xff0c;即List <LoanOrder>。 (2)然后从单个贷款订单实体LoanOrder去访问贷款人实体Loaner的信息。 2、实体之间的关系描述 (1)LoanOrder实体与Loaner…

JavaFX真实世界应用程序:EIZO CuratOR Caliop

JavaFX Real-World应用程序第四号称为Caliop 。 它是EIZO为医院手术室开发的CuratOR解决方案的前端。 前端在壁挂式控制台上运行&#xff0c;并允许操作团队查找有关患者的信息&#xff0c;控制各种视频源到不同监视器的路由&#xff0c;录制视频&#xff0c;拍摄照片/剧照。 …

netbeans代码提示_NetBeans可用性提示

netbeans代码提示的Java IDE都来了&#xff0c;因为在很长的路要走天的JBuilder的 &#xff08;尽管JBuilder中似乎是一个值得欢迎提前在时间&#xff09;。 当今的Java IDE&#xff08;例如NetBeans &#xff0c; Eclipse &#xff0c; IntelliJ IDEA和JDeveloper &#xff09…

推荐文章:机器学习:“一文读懂机器学习,大数据/自然语言处理/算法全有了...

PS:文章主要转载自CSDN大神"黑夜路人"的文章: http://blog.csdn.NET/heiyeshuwu/article/details/43483655 本文主要对机器学习进行科普,包括机器学习的定义、范围、方法,包括机器学习的研究领域&#xff1a;模式识别、计算机视觉、语音识别、自然语言…

java比较炫的登录界面_html+css实现漂亮的透明登录页面,HTML实现炫酷登录页面...

承蒙各位小伙伴的支持&#xff0c;鄙人有幸入围了《CSDN 2020博客之星》的前200名&#xff0c;现在进入投票环节&#xff0c;如果我平时写的文章和分享对你有用的话&#xff0c;请每天点击一下这个链接&#xff0c;投上你们宝贵的一票吧&#xff01;谢谢&#xff01;❤️ 每一票…

OpenMap教程第2部分–使用MapHandler构建基本地图应用程序–第1部分

1.简介 在第一个教程中&#xff0c;我们创建了一个基本的OpenMap GIS应用程序&#xff0c;该应用程序在JFrame中显示一个从文件系统加载的具有一个形状图层的地图。 该教程基于com.bbn.openmap.app.example.SimpleMap 。 在该教程中&#xff0c;我们使用了以下OpenMap类&#x…

java rx.observable_Rxjava2 Observable的条件操作符详解及实例

简要&#xff1a;需求了解&#xff1a;在使用 Rxjava 开发中&#xff0c;经常有一些各种条件的操作 &#xff0c;如比较两个 Observable 谁先发射了数据、跳过指定条件的 Observable 等一系列的条件操作需求&#xff0c;那么很幸运&#xff0c; Rxjava 中已经有了很多条件操作符…

Linux poll 和 select 机制

poll select 介绍 使用非阻塞 I/O 的应用程序常常使用 poll, select, 和 epoll 系统调用. poll, select 和 epoll 本质上有相同的功能: 每个允许一个进程来决定它是否可读或者写一个 或多个文件而不阻塞. 这些调用也可阻塞进程直到任何一个给定集合的文件描述符可用来 读或写.…

hprof 不大 泄露_HPROF –内存泄漏分析教程

hprof 不大 泄露本文将为您提供有关如何通过生成和分析Sun HotSpot JVM HPROF堆转储文件来分析JVM内存泄漏问题的教程。 一个现实的案例研究将用于此目的&#xff1a;Weblogic 9.2内存泄漏影响Weblogic Admin服务器。 环境规格 Java EE服务器&#xff1a;Oracle Weblogic Ser…

投资银行对Java进行的二十大核心面试问答

这是在金融领域&#xff08;主要是大型投资银行&#xff09;共享Java核心访谈问题和答案的新系列。 在JP Morgan&#xff0c;Morgan Stanley&#xff0c;Barclays或Goldman Sachs上会问许多这些Java面试问题。 银行主要从多线程 &#xff0c; 集合 &#xff0c;序列化&#xff…

java 支付重复问题_Airbnb支付系统如何在分布式环境下避免重复打款

原文链接&#xff1a;https://medium.com/airbnb-engineering/avoiding-double-payments-in-a-distributed-payments-system-2981f6b070bbAirbnb一直在将其基础架构迁移到面向服务的体系结构(SOA)。 SOA具有许多优势&#xff0c;例如使开发人员能够专业化并具有更快迭代的能力。…