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当中,细致考虑了多种情况。

原文地址:https://www.cnblogs.com/winderby/p/4090412.html