KISS - Keep it simple, stupid!

jshash – Implementando um Hash em JavaScript

postado por Gabriel Gilini em 21/04/2009 03:42:14
Tags: ,

Recentemente escrevi algum código javascript que realizava algumas requisições, e a fim de não buscar informações redundantes, armazenava um cache desses dados que chegavam. Simplificadamente, algo como:

var cache = {};
 
function buscaEProcessaDados(id){
	var dados;
	if(!cache[id]){
		// faz a requisição e retorna dados
		cache[id] = dados;
	}
	// Processa
}

E estava funcionando tudo bem. Mas pensando bem, isso não está muito seguro. Vamos supor que outro script na página execute o seguinte código:

Object.prototype.foo = function(){alert('te peguei!')};

e eu quisesse buscar algum dado que tenha id = foo.

buscaEProcessaDados('foo'); // :(

Mesmo não havendo nenhum dado armazenado na propriedade 'foo' daquele objeto cache que foi criado vazio mais acima, o teste

!!cache[id] //-> true

será interpretado como true, já que o JavaScript encontrará essa propriedade ao subir a cadeia de prototypes (escreverei sobre isso em breve) em busca de algo com nome 'foo'.

A maneira que encontrei para resolver este problema foi implementar um hash simples, com métodos de put, get e remove. O objeto que conterá as propriedades fica inacessível para código fora do objeto construído e as chaves são concatenadas a uma string gerada a partir do timestamp no momento da instanciação.

function Hash(){
    var _hash = {};
    var pre = '__' + (new Date()).getTime() + '__';
 
    function put(key, value){
        _hash[pre + key] = value;
        return this;
    }
 
    function get(key){
        return _hash[pre + key];
    }
 
    function remove(key){
        delete _hash[pre + key];
    }
 
    return {
        'put': put,
        'get': get,
        'remove': remove
    }
}

Utilizando o Hash, nosso código anterior fica assim:

var cache = new Hash();
 
function buscaEProcessaDados(id){
	var dados,
cached = cache.get(id);
	if(!cached){
		// faz a requisição e retorna dados
		cache.put(id, dados);
	}
	// Processa
}

e mesmo que a propriedade 'foo' esteja sendo herdada do Object.prototype, podemos ficar seguros que ela não interferirá em nossa hash:

typeof cache.foo == 'function' &&
typeof cache.get('foo') == 'undefined'; //-> true

É claro que esta Hash é bem primitiva e muitos métodos ainda podem ser implementados. Ainda assim ela funciona perfeitamente para propósitos simples como o demonstrado acima.

Como de costume, o código está hospedado no GitHub, e o download pode ser feito aqui.

Tags: ,

Trackback

Faça seu comentário

Topo

Sem comentários

Creative Commons License
Sou Ágil: KISS em http://kiss.souagil.com.br está licenciado sobre
Creative Commons Attribution-Share Alike 2.5 Brazil License.

souÁgil