Javascript缓存环,通过类切换方式来实现

定义一个固定尺寸的缓存,当它被填满时,新加入的元素会覆盖第一个(最老的)元素。一般情况我们会选择一个双头队列,可以从任意一头添加或删除数据。或者在运行时,根据缓存有没有满,去改变append函数的指向(方法切换)。但这里借用一下python中的self.__class__可以重新被指向一个新的类的思路(类切换),在javascript中实现一下。

function RingBuffer( size_max ){
    this.max = size_max;
    this.data = [];
    this.cur = 0;
    function _full(){
        this.append = function( x ){
            this.data[this.cur] = x;
            this.cur = ( this.cur + 1 ) % this.max;
        }
        this.tolist = function(){
            return this.data.slice(this.cur).concat(this.data.slice(0,this.cur));
        }
    }
    this.append = function( x ){
        this.data[this.cur] = x;
        this.cur ++ ;
        if( this.cur == this.max ){
            this.cur = 0;
            delete this.append;
            delete this.tolist;
            this.__proto__ = new _full();
        }
    }
    this.tolist = function(){
        return this.data;
    }
}


从未填满状态到填满状态的改变,会使实例的类进行切换,在python中可以通过对self.__class__的设置即可达到目的,但javascript中需要利用原型继承,来达到这一目的,上面的代码适用于firefox和chrome,对于IE,由于没有__proto__属性来引用原型对象(设置RingBuffer.prototype只会修改它自己原型对象的引用,不会修改已实例化对象的原型对象引用),所以当删除this中的方法后,由于找不到方法会报错。

对于IE,如果不能切换类,在javascript中,至少我们还能改变this的上下文

function RingBuffer( size_max ){
    this.max = size_max;
    this.data = [];
    this.cur = 0;
    function _full(){
        this.append = function( x ){
            this.data[this.cur] = x;
            this.cur = ( this.cur + 1 ) % this.max;
        }
        this.tolist = function(){
            return this.data.slice(this.cur).concat(this.data.slice(0,this.cur));
        }
    }
    this.append = function( x ){
        this.data[this.cur] = x;
        this.cur ++ ;
        if( this.cur == this.max ){
            this.cur = 0;
            _full.call(this);
        }
    }
    this.tolist = function(){
        return this.data;
    }
}


到底是运行时进行方法切换,还是进行类切换,python cookbook上建议:方法切换在需要更细行为粒度控制时适合,而在成组的切换所有方法时,类切换可能最佳。

参考资料:python cookbook 6.11

posted @ 2011-03-31 11:20  他山之石_  阅读(475)  评论(0编辑  收藏  举报