正文
jQuery.data的是jQuery的数据缓存系统。它的主要作用就是为普通对象或者DOM元素添加数据。
1 内部存储原理这个原理很简单,原本要添加在DOM元素本身的数据,现在被集中的存储在cache集合中。它们之间靠一个从1开始的数字键来联系着。这样DOM元素就不会像以前那么笨重了,更不会出现以前那种循环引用而引起的内存泄漏。现在DOM只需要保存好这个数字键值即可。这个属性值被保存在DOM元素的一个属性里,该属性名是由jQuery.expando生成的。
2 Data构造函数 Object.defineProperty( this.cache = {}, 0, { get: function() { return {}; } });首先来看Object.defineProperty函数,它的作用为:将属性添加到对象,或修改现有属性的特性。那我们先来看下ECMAScript5中的属性。
2.1 ECMAScript5中的属性ECMAScript5中有两种属性:数据属性和访问器属性。
2.1.1 数据属性:数据属性包含一个数据值的位置,在这个位置可以读取和写入值。有4种特性用来限制其行为。
①[[configurable]]
能否通过delete删除属性,能否修改属性的特性,能否把属性改为访问器属性。默认为true。
var obj={name:"abc"}; Object.defineProperty(obj,"name",{ configurable:false }); console.log(obj.name); delete obj.name; console.log(obj.name); Object.defineProperty(obj,"name",{ configurable:true });注意,一旦将 configurable 设为false,就再也设置不回去了。而且还会报错。
②[[enumerable]]
在for-in循环是否能获取到属性。默认为true。ECMAScript规定,由程序员定义的属性的该特性都为true。
③[[writable]]
能否修改属性的值。默认为true。
var obj={name:"abc"}; Object.defineProperty(obj,"name",{ writable:false }); console.log(obj.name); obj.name="111"; console.log(obj.name);④[[value]]
属性值所在的地方。读取属性值的时候获取的就是它,写属性值的时候也是往这里写。
var obj={name:"abc"}; console.log(obj.name); Object.defineProperty(obj,"name",{ value:111 }); console.log(obj.name); 2.1.2访问器属性访问器属性不包含实际的属性值,它包含两个函数(getter和setter)
①[[get]]
读取属性时调用的函数。默认为undefined
②[[set]]
写入属性时调用的函数。默认为undefined
var obj={}; Object.defineProperties(obj,{ name:{ get:function () { return obj["_name"]; }, set:function (name) { if(name != "C#"){ obj["_name"]=name; } } }, label:{ get:function () { return "你不能改变我!!!"; } } }); obj.name="JavaScript"; console.log(obj.name); obj.label="我偏要改变你!!!"; console.log(obj.label);上面给cache的属性0,只给了get属性。所以不能为该属性赋值。只能获取。
this.expando = jQuery.expando + Math.random();这个expando就是用来为DOM元素或者对象存储在cache中的键的。即它将作为DOM元素的一个属性被存储这。
红色画框内的属性名就是由上面的语句生成的,指明div1的属性存储在cache的1属性中。
Data.uid = 1;该属性表示cache的属性将从1开始自增。因为0已经被这个冻结的空JSON占用了,所以从1开始。我们下次再为某DOM元素添加属性时,它将被保存在cache的2属性中。 3 允许的添加属性的元素 Data.accepts = function( owner ) { return owner.nodeType ? owner.nodeType === 1 || owner.nodeType === 9 : true; };这段代码写的非常干练。表示如果owner是DOM元素则只有ELEMENT_NODE和DOCUMENT_NODE两种元素能添加属性,如果owner是一个对象,则都可以添加属性。 4 原型属性 4.1 key: function( owner ) { if ( !Data.accepts( owner ) ) { return 0; }
如果owner不能被添加data,则返回cache的第0个元素。
unlock = owner[ this.expando ];这里获取的就是
如果能从owner中找到这个属性,则说明以前为它添加过值,也就是说,它已经拥有了一个在cache中的key。
if ( !unlock ) { unlock = Data.uid++; try { descriptor[ this.expando ] = { value: unlock}; Object.defineProperties( owner, descriptor ); } catch ( e ) { descriptor[ this.expando ] = unlock; jQuery.extend( owner, descriptor ); } }