I have a set of objects and I want to be able to use the same syntax to either
- build a new object or
- load an existing object.
I’ve built a “cache” that takes the object and the context that the object was created using and uses this data to see if the object has been previously created. So, for example, if I build theObject = new myObject(param1, param2), the cache would save the object as { obj: theObject, context: { param1: param1, param2: param2 } } and would be loaded again if I give it a context with the same values of param1 and param2.
I thought I was being clever and would be able to build the object like this:
myObject = function(param1, param2) {
var context = { param1: param1, param2: param2 };
var cacheHit = this.cache.find(context);
if (cacheHit) return cacheHit; // <-- Doesn't work :(
this.param1 = param1;
this.param2 = param2;
this.cache.save(this, context);
};
myObject.prototype = { cache: new myCacheObject }; // Shared cache in all instances
Sadly, I’ve learned that the new keyword means that I cannot use a return statement. I’d like for the cache collections to be internalized so that it’s possible to build similar objects without a built-in cache and they would work the same. However, I don’t think that I can do this with the new keyword.
How would I go about accomplishing this?
Update:
It turns out that this approach actually does work and my problem was stemming from inheritance (particularly since this is JavaScript inheritance). When extending this object, I used the following syntax:
myObject = function(param1, param2) {
if (arguments.length) {
var context = { param1: param1, param2: param2 };
var cacheHit = this.cache.find(context);
if (cacheHit) return cacheHit;
this.param1 = param1;
this.param2 = param2;
this.cache.save(this, context);
}
};
// Extended from myObject
anotherObject = function(foo, bar) {
// Call parent constructor
myObject.call(this, foo, bar);
};
anotherObject.prototype = new myObject;
anotherObject.prototype.constructor = anotherObject;
Since calling the parent constructor can’t force the child to return a value, the child has to explicitly denote this.
anotherObject = function(foo, bar) {
return myObject.call(this, foo, bar);
};
Hopefully, I can come up with a cleaner way of doing this since, if the child class performs anything in its constructor, I will have to always check if a value was returned.
anotherObject = function(foo, bar) {
var possibleCacheHit = myObject.call(this, foo, bar);
if (possibleCacheHit) return possibleCacheHit;
// Do stuff
};
Lucky you, that’s not true. Provided that you return a non-null object reference (see the linked answer for the specifics), the
newoperator will actually let you do what you want.