先看用法:
看jq源码
<span style="font-size:14px;">var data_user
function Data() {
Object.defineProperty( this.cache = {}, 0, {
get: function() {
return {};
}
});
this.expando = jQuery.expando + Math.random();
}
Data.uid = 1;
Data.accepts = function( owner ) {
return owner.nodeType ?
owner.nodeType === 1 || owner.nodeType === 9 : true;
};
Data.prototype = {
key: function( owner ) {
if ( !Data.accepts( owner ) ) {
return 0;
}
var descriptor = {},
unlock = owner[ this.expando ];
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 );
}
}
if ( !this.cache[ unlock ] ) {
this.cache[ unlock ] = {};
}
return unlock;
},
set: function( owner, data, value ) {
var prop,
unlock = this.key( owner ),
cache = this.cache[ unlock ];
if ( typeof data === "string" ) {
cache[ data ] = value;
} else {
if ( jQuery.isEmptyObject( cache ) ) {
jQuery.extend( this.cache[ unlock ], data );
} else {
for ( prop in data ) {
cache[ prop ] = data[ prop ];
}
}
}
return cache;
},
get: function( owner, key ) {
var cache = this.cache[ this.key( owner ) ];
return key === undefined ?
cache : cache[ key ];
},
access: function( owner, key, value ) {
var stored;
if ( key === undefined ||
((key && typeof key === "string") && value === undefined) ) {
stored = this.get( owner, key );
return stored !== undefined ?
stored : this.get( owner, jQuery.camelCase(key) );
}
this.set( owner, key, value );
return value !== undefined ? value : key;
},
remove: function( owner, key ) {
var i, name, camel,
unlock = this.key( owner ),
cache = this.cache[ unlock ];
if ( key === undefined ) {
this.cache[ unlock ] = {};
} else {
if ( jQuery.isArray( key ) ) {
name = key.concat( key.map( jQuery.camelCase ) );
} else {
camel = jQuery.camelCase( key );
if ( key in cache ) {
name = [ key, camel ];
} else {
// If a key with the spaces exists, use it.
// Otherwise, create an array by matching non-whitespace
name = camel;
name = name in cache ?
[ name ] : ( name.match( core_rnotwhite ) || [] );
}
}
i = name.length;
while ( i-- ) {
delete cache[ name[ i ] ];
}
}
},
hasData: function( owner ) {
return !jQuery.isEmptyObject(
this.cache[ owner[ this.expando ] ] || {}
);
},
discard: function( owner ) {
if ( owner[ this.expando ] ) {
delete this.cache[ owner[ this.expando ] ];
}
}
};
data_user = new Data();
jQuery.extend({
acceptData: Data.accepts,
hasData: function( elem ) {
return data_user.hasData( elem );
},
data: function( elem, name, data ) {
return data_user.access( elem, name, data );
},
removeData: function( elem, name ) {
data_user.remove( elem, name );
}
});</span>
1、
Data构造函数,defineProperty的作用:定义Data.cache = { 0:function(){return {}} },这里的k值和方法是不能修改,this.expando,取一个随机数
function Data() {
Object.defineProperty( this.cache = {}, 0, {
get: function() {
return {};
}
});
this.expando = jQuery.expando + Math.random();
}
2、
$.data()方法,实际调用的是Data的实例方法
data_user = new Data();
jQuery.extend({
acceptData: Data.accepts,
hasData: function( elem ) {
return data_user.hasData( elem ) || data_priv.hasData( elem );
},
data: function( elem, name, data ) {
return data_user.access( elem, name, data );
},
removeData: function( elem, name ) {
data_user.remove( elem, name );
}
});
3
这里做的判断意思是:当传入的对象有nodeType,并且等于1(元素)或9(document),或者是其他对象,就返回真
Data.accepts = function( owner ) {
return owner.nodeType ?
owner.nodeType === 1 || owner.nodeType === 9 : true;
};
4、this.expando是随机数,放到对象身上。unlock是cache的k值
对应关系:{this.expando: unlock},cache = {unlock: value}
key: function( owner ) {
//这里进行筛选,只有通过的对象才能继续,没有通过的对象都返回0,因为0不能修改,不能通过的对象所有取值都是{}。
if ( !Data.accepts( owner ) ) {
return 0;
}
//descriptor后面会赋值为:{this.expando: unlock}
var descriptor = {},
unlock = owner[ this.expando ];
//如果unlock不存在,就赋值Data.uid++,并且给传入对象(假如为obj)赋值:obj[this.expando] = unlock
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 );
}
}
//缓存,和obj的unlock对应起来
if ( !this.cache[ unlock ] ) {
this.cache[ unlock ] = {};
}
return unlock;
}
5、set为赋值操作
set: function( owner, data, value ) {
var prop,
//获取对象对应缓存的k值,并且通过k值取出缓存空间
unlock = this.key( owner ),
cache = this.cache[ unlock ];
//这里为for in循环赋值
if ( typeof data === "string" ) {
cache[ data ] = value;
} else {
if ( jQuery.isEmptyObject( cache ) ) {
jQuery.extend( this.cache[ unlock ], data );
} else {
for ( prop in data ) {
cache[ prop ] = data[ prop ];
}
}
}
return cache;
}
6、通过传入对象,要取的K值,获取对应的值。如果传入的key没有,则返回所有缓存的值
get: function( owner, key ) {
var cache = this.cache[ this.key( owner ) ];
return key === undefined ?
cache : cache[ key ];
}
7、
access方法,通过传入的参数值,分别调用赋值/取值方法
8、
remove方法:删除缓存中对应的K值
hasData方法:判断对象身上是否有缓存(对应的cache中是否还存在有值)
discard:删除对象身上的随机数值,作用彻底清空和缓存的绑定关系