深入理解jQuery.data() 的实现方式

jQuery.data() 的作用是为普通对象或 DOM Element 附加(及获取)数据。 

下面将分三个部分分析其实现方式: 

1. 用name和value为对象附加数据;即传入三个参数,第一个参数为需要附加数据的对象,第二个参数为数据的名称,第三个参数为数据的值。当然,只是获取值的话,也可以不传入第三个参数。 

2. 用另一个对象为对象附加数据;即传入两个参数,第一个参数为需要附加的数据对象(我们称之为“obj”),第二个参数也是一个对象(我们称之为“another”);“another”中包含的键值对将会被复制到 “obj” 的数据缓存(我们称之为“cache”)中。 

3. 为 DOM Element 附加数据;DOM Element 也是一种 Object ,但 IE6、IE7 对直接附加在 DOM Element 上的对象的垃圾回收存在问题;因此我们将这些数据存放在全局缓存(我们称之为“globalCache”)中,即 “globalCache” 包含了多个 DOM Element 的 “cache”,并在 DOM Element 上添加一个属性,存放 “cache” 对应的 uid 。

用name和value为对象附加数据

使用 jQuery.data() 为普通对象附加数据时,其本质是将一个 “cache” 附加到了对象上,并使用了一个特殊的属性名称。 

存放数据的 “cache” 也是一个 object,我们为 “obj” 附加的数据实际上成为了 “cache” 的属性。而 “cache” 又是 “obj” 的一个属性,在 jQuery 1.6中,这个属性的名称是 “jQuery16”加上一个随机数(如下面提到的 “jQuery16018518865841457738” )。

我们可以用下面的代码来测试 jQuery.data() 的功能:

<script type="text/javascript" src="https://www.jb51.net/jqueryjs"></script> <script> obj = {}; $data(obj, 'name', 'value'); documentwrite("$data(obj, 'name') = " + $data(obj, 'name') + '<br />'); for (var key in obj) { documentwrite("obj" + key + 'name = ' + obj[key]name); } </script>

显示结果为:

$.data(obj, 'name') = value obj.jQuery16018518865841457738.name = value

在这段代码中,我们首先在 “obj” 上附加了一个属性(名称为“name”,值为“value”),然后通过 $.data(obj, 'name') 来获取所附加的数据。为了深入了解其中的实现机制,我们有使用了一个循环来获取 “obj” 的属性,实际上是取出了在 “obj” 上附加的 “cache”对象。

可以看到,jQuery.data() 实际上为 “obj” 附加到了名为 “jQuery16018518865841457738” (这个名称是随机的)的对象,也就是 “cache” 上。用 jquery.data() 方式为对象附加的属性实际上成为了这个 “cache” 的属性。

我们可以用下面的代码实现类似的功能:

$ = function() { var expando = "jQuery" + ("6" + Mathrandom())replace(/\D/g, ''); function getData(cache, name) { return cache[name]; } function setData(cache, name, value) { cache[name] = value; } function getCache(obj) { obj[expando] = obj[expando] || {}; return obj[expando]; } return { data : function(obj, name, value) { var cache = getCache(obj); if (value === undefined) { return getData(cache, name); } else { setData(cache, name, value); } } } }();

function 中的第一行代码定义了 “expando” ,即 "jQuery1.6" 加上一个随机数(0.xxxx),并将其中非数字的部分去掉;这种格式将在jQuery的其他地方用到,这里不做探讨;只需要知道这是一个特殊的名称,并且可以用于标识不同的页面(比如不同 iframe 中的 “expando” 就会有所不同)。

接下来定义了获取数据的函数 getData(), 即从 “cache” 中获取一个属性;实际上也就是返回 cache[name] 。 

然后是 setData() 函数,用于设置 “cache” 的属性;实际上也就是设置 cache[name] 的值。 

之后是 getCache() , 获取 “obj” 上的 “cache”,即 obj[expando];如果 obj[expando] 为空,则进行初始化。 

最后公开了 data 方法,先根据传入的 “obj”,获取附加在 “obj” 上的 “cache”; 当传入两个参数时,调用 getData()方法;当传入三个参数时,则调用 setData() 方法。

用另一个对象为对象附加数据

除了以提供 name 和 value 的方式进行赋值,我们还可以直接传入另一个对象( “another” )作为参数。这种情况下,“another” 的属性名称和属性值将被视为多个键值对,从中提取的 “name” 和 “value” 都会被复制到目标对象的缓存中。

功能测试代码如下:

<script type="text/javascript" src="https://www.jb51.net/jqueryjs"></script> <script> obj = {}; $data(obj, {name1: 'value1', name2: 'value2'}); documentwrite("$data(obj, 'name1') = " + $data(obj, 'name1') + '<br />' ); documentwrite("$data(obj, 'name2') = " + $data(obj, 'name2') + '<br />'); for (var key in obj) { documentwrite("obj" + key + 'name1 = ' + obj[key]name1 + '<br />'); documentwrite("obj" + key + 'name2 = ' + obj[key]name2); } </script>

显示结果如下:

$.data(obj, 'name1') = value1 $.data(obj, 'name2') = value2 obj.jQuery1600233050178663064.name1 = value1 obj.jQuery1600233050178663064.name2 = value2

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwxzsx.html