前言:jQuery 作为前端使用最多最广泛的 JS 库,其源码每个 JSer 都应该研究一下。早就打算看却一直被各种事拖着,上次某公司面试时被问到 jQuery 中 data 方法是如何实现的,结果答不上来懊悔不已。现在终于下决心开始看 jQuery 的源码,就从 data 方法开始。本人也是前端新手,如果文章中有理解不当或者错误之处,欢迎留言指出,3Q~ jQuery 版本为 1.8.2

data() 的使用方法

// 向一个 dom 元素绑定数据
$("#header").data("aaa", 123); // 给 header 绑定了一个数据其key为"aaa",value为123 $("#header").data({"name": "xiaoming", "age": 20}); // 也可以将所有数据作为一个对象直接整体绑定在元素上 // 获取绑定的数据
$("#header").data("aaa"); // 获取 header 上绑定的 key 为"aaa"的值,如果没有在 cache 对象(下面分析源码时会讲到)中找到,会解析元素的 html 5 标签 data-*,并将值存入 cache 对象 $("#header").data(); // 获取 header 上绑定的所有数据 // 移除绑定的数据
$("#header").removeData("name"); // 移除 header 上绑定的 key 为 name 的数据 $("#header").removeData(); // 移除 header 上绑定的所有数据

源码中 data() 方法相关的代码

jQuery.extend({
  // 全局变量,负责保存给每个 dom 元素绑定的数据
cache: {}, // 全局变量,当已经绑定的数据被 cleanData 方法清除以后,回收的 id保存在改变量中
deletedIds: [], // 当前版本没有用到 在(1.9/2.0)版本中将移除
uuid: 0, // 为 jQuery实例 添加一个唯一标示,区别不同的 jQuery 实例(比如同一工程内不同版本的 jQuery)绑定的数据,比如: jQuery164018232414545491338,前缀+版本号+随机数
expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), // 下面几类元素是不给绑定数据的,如果绑定会报错
noData: {
"embed": true,
// 除了 flash 之外的 object 对象
"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
"applet": true
}, // 判断一个元素是否已经绑定有数据
hasData: function( elem ) { }, // 绑定数据 ( pvt 为 false 时,数据会添加到 cache 中元素对应 id 下的data 属性中,pvt 为 true 则把绑定的数据直接添加到 cache 中元素对应的id 下,与 data 属性并列。jQuery 绑定内部数据 events、handle 等都是通过 _data 方法将 pvt 设置为 true )
data: function( elem, name, data, pvt /* 该参数内部使用 */ ) { }, // 移除数据
removeData: function( elem, name, pvt /* 该参数内部使用 */ ) { }, // 仅限内部调用,添加内部数据
_data: function( elem, name, data ) { }, // 判断一个 dom 节点是否可以绑定数据
acceptData: function( elem ) { }, // 清除节点上绑定的事件和节点的 jQuery 实例标识属性
cleanData: function( elems, /* internal */ acceptData ) { }
}); jQuery.fn.extend({
// 提供给开发者调用的绑定数据方法
data: function( key, value ) { }, // 提供给开发者调用的移除数据方法
removeData: function( key ) { }
}); // 解析元素中 html5 标签 data-* 的值。如果在 cache 对象当中已经获取到对应值则直接返回不解析 data-* 属性,否则解析 data-* 属性并且将数据添加至 cache 对象中存储。
function dataAttr( elem, key, data ) { } // 判断cache 下保存的数据对象是否为空,当且仅当数据对象只有一个 data 属性,且值为空时才为空
function isEmptyDataObject( obj ) { }

jQuery.extend 与 jQuery.fn.extend 的区别在于:

jQuery.extend 是在 jQuery 这个构造函数上扩展的方法,调用的时候写成 $.xxx 或者 jQuery.xxx

jQuery.fn.extend 是在 jQuery 原型上扩展的方法,原型上的方法被所有 jQuery 对象共享,调用的时候为 $().xxx

给元素绑定的数据的保存格式

$("#header").data("title", "hello world");

// 执行后打印 $.cache 结果为
{
1: {
data: {
title : "hello world"
}
}
}
// 并且查看 header 元素,发现属性中多了一行 "jQuery18102873769768048078: 1" 其中 key 值那一长串为 jQuery 实例唯一标识,1 是 header 元素绑定的数据在 cache 对象中对应的属性名,该值每次增加 1, $("#footer").data("foot", "goodbye"); // 执行后打印 $.cache 结果为
{
1: {
data: {
title : "hello world"
}
},
2: {
data: {
foot : "goodbye"
}
}
}
// 同样 footer 元素的属性中多了一行 "jQuery18102873769768048078: 2"

给元素绑定的事件处理程序也会保存在 cache 对象中

$("#header").click(function(){});

// 绑定点击事件后,$.cache 的内容为
{
1: {
data : {
title : "hello world"
},
events : {
click : [] // click 对应的数组内容省略
},
handle : function(){ } // function 的内容及属性省略
}
2: {
data : {
foot : "goodbye"
}
}
}
// 可见给 dom 元素绑定事件处理程序后,多了 events 和 handle 两个属性,jQuery 自动将这些数据绑定到 cache 对象中元素对应的数据对象中

通过全局对象 cache 来保存 dom 元素上绑定的数据,可以避免 dom 对象和 js 对象之间互相引用导致的循环引用问题。

data() 方法相关事件

与 data() 方法相关的事件有 getData、setData、changeData,使用方法见代码

$("#header").bind("getData" ,function(){
console.log("getData");
})
.bind("setData" , function(){
console.log("setData");
})
.bind("changeData" , function(){
console.log("changeData");
});
$("#header").data("name" , "Austin"); //打印 "setData" "changeData"
$("#header").data("name"); //打印"getData"

jQuery 中 data 方法的实现原理的更多相关文章

  1. 关于JQuery中$.data绑定数据原理或逻辑

    问题: JQuery中,对于.data([key],[value])函数,当使用其进行数据绑定时,假设要绑定的数据是“引用数据类型”,也就是对象:那么.data函数绑定的是该对象的副本还是该对象的一个 ...

  2. jQuery中ready方法的实现

    https://blog.csdn.net/major_zhang/article/details/80146674 先普及一下jquery.ready()和window.onload,window. ...

  3. jquery中on/delegate的原理

    jquery中on/delegate的原理 早期版本中叫delegate, 后来有过live函数,再后来统一用on.下面的方法等效: // jQuery 1.3 $(selector).(events ...

  4. jQuery中getJSON跨域原理详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp28 jQuery中getJSON跨域原理详解 前几天我再开发一个叫 河蟹工 ...

  5. js进阶 12-13 jquery中one方法和trigger方法如何使用

    js进阶 12-13 jquery中one方法和trigger方法如何使用 一.总结 一句话总结: 1.one()方法和on()方法的区别是什么? 除了one()只执行一次,其它和on()一模一样,包 ...

  6. JVM源码分析之深入分析Object类finalize()方法的实现原理

      原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 ​“365篇原创计划”第十篇. 今天呢!灯塔君跟大家讲: 深入分析Object类finalize()方法的实现原理 finalize 如果 ...

  7. Python描述符以及Property方法的实现原理

    Python描述符以及Property方法的实现原理 描述符的定义: 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实了__get__(),__set__(),__delete__()中 ...

  8. 详解JS中 call 方法的实现

    摘要:本文将全面的,详细解析call方法的实现原理 本文分享自华为云社区<关于 JavaScript 中 call 方法的实现,附带详细解析!>,作者:CoderBin. 本文将全面的,详 ...

  9. Atitit paip.对象方法的实现原理与本质.txt

    Atitit paip.对象方法的实现原理与本质.txt 对象方法是如何实现的1 数组,对象,字典1 对象方法是如何实现的 这显然是一个对象方法调用.但对象方法是如何实现的呢?在静态语言中,因为有编译 ...

随机推荐

  1. 当一个activity中按钮过多时怎么办?

    这几天看极客学院的视频,跟视频中的老师学到的一些小技巧~~ .setOnClickListener(this) 通过重写this(我猜的是重写),下面有onClicked() package exam ...

  2. 高通CP Crash分析调试

    1. 转换tlcore文件 获取 EBICS0.BIN tl2elf --qconly tlcore 2.使用T32 命令把Riva的dump信息从EBICS0文件分离出来 data.load.BIN ...

  3. JQuery正则验证

    比较常用的: function checkIshanzi(s) { //var patrn = /^[\u2E80-\u9FFF]$/; //Unicode编码中的汉字范围 /[^\x00-\x80] ...

  4. 第十三周学习笔记(编辑器选错了重发了这一个 原博客的确周天晚上提交了orz)

    并发:逻辑控制流在时间上的重叠. 构造并发程序的方法: 进程 I/O多路复用 线程 基于进程的并发编程 假设我们有两个客户端和一个服务器,服务器正在监听一个监听表述符上的请求.现在假设服务器接受了客户 ...

  5. F - To the Max

    Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous s ...

  6. 由于xrdp、gnome和unity之间的兼容性问题,在

    由于xrdp.gnome和unity之间的兼容性问题,在Ubuntu 14.04版本中仍然无法使用xrdp登陆gnome或unity的远程桌面,现象是登录后只有黑白点为背景,无图标也无法操作.与13. ...

  7. find查找命令的各种使用方法

    find是文件查找工具,实时查找,速度慢,精确匹配 find命令基本使用格式 find [options] [查找路径] [查找条件] [处理动作] 查找路径:默认为当前目录 查找条件:默认为查找指定 ...

  8. [NOIP2011] mayan游戏(搜索+剪枝)

    题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游戏通关是指在规定 ...

  9. 《统计推断(Statistical Inference)》读书笔记——第4章 统计分布族

    数据分析工作中最常和多维随机变量打交道,第四章介绍了多维随机变量的基本知识,其中核心概念是条件分布和条件概率.条件分布和条件概率可以抽象出条件期望的概念,在随机分析的研究中,理解随机积分和鞅理论和关键 ...

  10. 颤抖吧,骚年们,2016年末最牛逼的sql语句

    select channel_name,from_unixtime(createTime,'%Y-%m-%d') as tdate,count(deviceid) '安装量',count(case w ...