jQuery源码笔记——数据缓存
数据缓存是为了解决内存泄露,他的原理是,当我们将数据存储到一个对象上面,实际上是将所有的数据存到一个单独的数据对象里,而这个对象只提供一个接口,这个接口可以访问自己存在数据对象里自己的数据。
这是一个简单的数据缓存
var cache= {}; function set(obj,name,value){ //在对象上存储一个属性,用作访问数据的接口 obj.expando = 1; //初始化对象,并在我们接口所提供的位置存放数据 cache[obj.expando] = {} cache[obj.expando][name] = value } function get(obj,name){ //实际就是通过对象上的expando指定在数据中位置去访问的自己的数据。 return cache[obj.expando][name] } var obj2 = {}; set(obj2,"name","winder"); console.log(get(obj2,"name")) //winder console.log(obj2) // Object { expando: 1} console.log(cache[1]) // Object { name: "winder" }
由代码可以很清楚看到,我们实际访问的是数据对象中,1引用的对象;而如何找到数据的位置,则由存储在对象上的一个接口属性提供。
当我们把他运用在jQuery中
//mini的jQuery框架。 var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context ); }; jQuery.fn = jQuery.prototype = { selector: "", init: function(selector){ var result = document.querySelectorAll(selector); for(var i = 0;i < result.length;i++){ this[i] = result[i] } this.length = result.length; }, constructor : jQuery } jQuery.fn.init.prototype = jQuery.fn; //定义date构造函数 function Data(){ this.cache = {} //默认带有随机数属性 this.expando = Math.random() } //设置在数据对象中的位置的辅助属性 Data.uid = 1; Data.prototype = { //判断对象是否有接口属性, //没有接口时,新建接口 key: function( owner ) { var descriptor = {}, unlock = owner[ this.expando ]; if ( !unlock ) { unlock = Data.uid++; descriptor[ this.expando ] = { value: unlock }; Object.defineProperties( owner, descriptor ); } //确保在缓存中存在 if ( !this.cache[ unlock ] ) { this.cache[ unlock ] = {}; } return unlock; }, //向缓存中添加数据 set: function( owner, data, value ) { var unlock = this.key( owner ); var cache = this.cache[ unlock ]; cache[ data ] = value; return cache; }, //获取数据 get: function( owner, key ) { var cache = this.cache[ this.key( owner ) ]; return cache[ key ]; }, //access实际就是一个访问路由,根据参数判断是设置还是获取 access: function( owner, key, value ) { //访问 if ((typeof key === "string") && value === undefined ) { return this.get( owner, key ); } //设置 this.set( owner, key, value ); return value }, } var data_user = new Data() jQuery.data = function( elem, name, data ) { return data_user.access( elem, name, data ); } //测试 var obj = {} jQuery.data(obj,"name","winder") console.log(jQuery.data(obj,"name")) //winder console.log(obj) //里面的里面是0.6637197330750032:1 console.log(data_user.cache[1])//Object { name: "winder" }
采用向对象中添加随机数属性,是为了屏蔽除内部外任何访问,保证缓存中数据安全。
添加jQuery对象方法
//mini的jQuery框架。 var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context ); }; jQuery.fn = jQuery.prototype = { selector: "", init: function(selector){ var result = document.querySelectorAll(selector); for(var i = 0;i < result.length;i++){ this[i] = result[i] } this.length = result.length; }, constructor : jQuery } jQuery.fn.init.prototype = jQuery.fn; //定义date构造函数 function Data(){ this.cache = {} //默认带有随机数属性 this.expando = Math.random() } //设置在数据对象中的位置的辅助属性 Data.uid = 1; Data.prototype = { //判断对象是否有接口属性, //没有接口时,新建接口 key: function( owner ) { var descriptor = {}, unlock = owner[ this.expando ]; if ( !unlock ) { unlock = Data.uid++; descriptor[ this.expando ] = { value: unlock }; Object.defineProperties( owner, descriptor ); } //确保在缓存中存在 if ( !this.cache[ unlock ] ) { this.cache[ unlock ] = {}; } return unlock; }, //向缓存中添加数据 set: function( owner, data, value ) { var unlock = this.key( owner ); var cache = this.cache[ unlock ]; cache[ data ] = value; return cache; }, //获取数据 get: function( owner, key ) { var cache = this.cache[ this.key( owner ) ]; return cache[ key ]; }, //access实际就是一个访问路由,根据参数判断是设置还是获取 access: function( owner, key, value ) { //访问 if ((typeof key === "string") && value === undefined ) { return this.get( owner, key ); } //设置 this.set( owner, key, value ); return value }, } var data_user = new Data() jQuery.data = function( elem, name, data ) { return data_user.access( elem, name, data ); } //简化的jQuery对象API方法 jQuery.fn.data = function( key, value ){ for(var i = 0;i < this.length; i++){ return jQuery.data(this[i],key,value) } } //测试 var $emample = jQuery("#example") $emample.data("name","winder"); console.log($emample.data("name")) //winder
这是一个极简化的API。而在原版jQuery当中,细致考虑了多种情况。