views:

79

answers:

2

I'm not new to JavaScript, but I've never really had too much in-depth knowledge of how it works. I'm currently developing some software for a cell phone that is done completely in JavaScript. Everything runs fine, except that once in a while the garbage collector kicks in, and everything stops momentarily.

The problem is that objects are constantly being destroyed and created. There are many objects that are also similar, but not the same.

The solution is simple: whenever an object is no longer needed, put it in a linked list that acts as a recycle bin. Whenever we're ready to create another object of a similar type (most of the same properties), get the object from the list and set it up as necessary. However, I'm not entirely sure on the conversion part.

I understand that every object in JavaScript is essentially just a hash table, but I'm still not exactly sure how I should approach the problem. I'll give an example of the problem below:

var type1 = Class.create({ ... });
var type2 = Class.create({ some of the same properties + some different ones });

Now I have a type1 that's not being used and I want to use it as a type2. What is the best way of doing this?

+2  A: 

It really depends on how you exercises the objects in your code. If you are really strict and doesn't do clever things with regards to detecting the object's type... then it'd be safe to suggest that you simply re-use the objects as-is ala duck typing style. Just fill in the missing "some different ones" would probably be enough.

On the other hand, if you're not sure or have code that mingles and tingles with the properties of the object, such as:

if (obj.color == "white" && obj.legs == 2 && obj.family != "swan")
{
    // we have a duck!
}

Then you will need to be strict on how you "shape" your objects.

You can essentially removes a "key" from an object with the delete statement

myObj.a = "HELLO";
alert(myObj["a"]); // => alerts "HELLO"

delete myObj.a;
alert(myObj["a"]); // => alerts "undefined"

And from that you can use a simple for loops to "resets" the object before re-using it as something else:

for (var key in myObj)
    delete myObj[key];

You can also do a simple differences check using the if operator:

var refObj = { /* obj of desired type */ };
var newObj = { /* obj fetched from recycler */ };

for (var key in newObj)
    if (refObj[key] == undefined)  
        delete newObj[key];          // removes alien keys found in newObj
    else
        newObj[key] = refObj[key];   // add/resets keys so it looks like refObj


However I would rather suggest that you only re-use objects of the exact same type or rethink your class/object hierarchies to avoid this overhead.

I sense that doing this would be getting too clever. Wasn't re-cycling objects the job of the JS runtime and not the developer?

chakrit
virtually every class is the same. Every class I've made is designed to be drawn to the canvas so it has info about its width, height, position, rotation, and scale. Every object is also capable of being in a linked list so that have a next and previous parameter. The differences come from the think() method that every object has. When reusing an object, all I'd want to do is reinitialize its basic parameters (giving it positional context) and change the think method that is used to determine the behavior of the object. The idea of deleting parameters is interesting but unnecessary.
Mark
I was kind of hoping that there was some way to use the new keyword to reinitialize an object -.- All of the info needed is already in the constructor and prototype so I was hoping I'd be able to use those. From what you've posted, it looks like I'd have to just create a function to convert the object.
Mark
+1  A: 

Answering @Mark comments

So basically, your object initialization would be:

var newObj = fetchFromList();

resetBasicParameters(newObj);

newObj.think = function() { /* a new implementation */ };

You can share the "a new implementation" part among multiple objects and still be able to access variables/properties inside the objects by utilizing the this keyword:

function thinkInTriangle() { /* trigonometries */ }
function thinkInRects() { /* geometries */ }
function thinkInPolygons() { /* crazy geometries */ }

function createRect() { return getObjFromPool(thinkInRects); }
function createTriangle() { return getObjFromPool(thinkInTriangle); }
function createPolygon() { return getObjFromPool(thinkInPolygons); }

function getObjFromPool(thinkFunc)
{
    var newObj = fetchFromList();
    resetBasicParameters(newObj);

    newObj.think = thinkFunc
}

Each of the thinkInX function, when wired to an instance of object will have the this keyword pointing to the particular object it is in. So this basically means that the think function can be detached from any/all objects and be manipulated at wills.

Not sure if this'd would help. Awaiting feedback.

chakrit
That's essentially the solution I'm looking at right now. I have lists of similar objects so that when I fetch an object, chances are I won't be creating new parameters (there should be less than 3 parameters that aren't common of all the similar objects). I guess I'll move the think logic out of the prototype and into stand alone functions so I can just set it like you have above. Thanks!
Mark
@Mark Glad that atleast it didn't go to waste :)
chakrit