Wednesday, July 16, 2008

JavaScript Relator Object, aka unobtrusive informations

Have you never though about add, modify, or remove a generic information from a variable, and without changing variable itself?
This is all about what my last simple creation does.



Relator Object Concept


The main purpose for this object is to associate every kind of information, value, or function, into a generic variable, whatever it is, and without modifying its native state.
To obtain this result, I have used a 1:1 relationship between a stack that will contain every stored variable, and another one that will contain related objects.

Stack = [1, 2, 3];
RelatedObject = [{}, {}, {}];

// add a property
RelatedObject[Stack.indexOf(2)].description = "Number 2";

// remove a property
Stack.splice(0, 1);
RelatedObject.splice(0, 1);

// situation
Stack = [2, 3];
RelatedObject = [{description:"Number 2"}, {}];

Using above strategy we obtain 2 benefits:

  1. The Stack does not cause memory leaks

  2. both Stack and RelatedObject are alway as small, and fast, as possible





Related Object Code



var Relator = function(Array, Object){
// (c) Andrea Giammarchi - Mit Style License
if(!Array.indexOf)
Array.indexOf = function(value){
for(var i = 0, length = Array.length; i < length; i++)
if(Array[i] === value)
return i;
return -1
};
return {
get:function(value){
return Object[Array.indexOf(value)]
},
set:function(value){
var i = Array.indexOf(value);
return ~i ? Object[i] : Object[Array.push(value) - 1] = {}
},
del:function(value){
var i = Array.indexOf(value);
if(~i){
Array.splice(i, 1);
Object.splice(i, 1);
};
return this
}
}
}([], []);

I hope, and I suppose, the 3 methods API talks by itself.
set is used to create a relation, if this does not exists, returning associated object.
get is used only to get a relation or undefined, if this does not exist.
Finally, del, is used to delete the relation, reducing the Array size, and deleting related Object.



Some Example


Try to imagine that we are using a library, but we would be able to add any sort of info about them, or implement something for our purpose.

var jQueryMore = Relator.set(jQuery);
jQueryMore.details = "jQuery library";
jQueryMore.isCompatible = function(){
return window.$ === jQuery;
};

// in every other piece of code ...
if(Relator.get(jQuery).isCompatible())
alert("I am using the " + Relator.get(jQuery).details);
// I am using the jQuery library




Relator Performances


IE a part, since it still does not implement natively the old indexOf Array method, performance to set, access, modify, or delete related informations, are probably the best possible, closes to zero value.
We can test by ourself using 10000 stored relations, and accessing to the last one.

for(var i = 0; i < 10000; i++)
Relator.set("number " + i).description = "The " + i + " number";

time = new Date;
description = Relator.get("number " + 9999).description;
time = new Date - time;
alert([description, time]);




Conclusion


The Relator object is based on our own variables, and it is not a container, a register, or a IOC emulator, at all.
At the same time, to be able to relate an object with a generic variable (undefined included, as example), it needs to store them in the Stack.
This could be a problem for memory leaks, but only if we forget to use the del method, to remove the assigned, and protected, relation between our global scope whatever, and the internal object dedicated relation.
Applications? In my mind, this object could make a lot of stuff simpler than ever, specially in those case where we would like, for example, monitor variables, singleton or global instances, during our script life :)

No comments:

Post a Comment