I have a singleton object that use another object (not singleton), to require some info to server:
var singleton = (function(){
/*_private properties*/
var myRequestManager = new RequestManager(params,
//callbacks
function(){
previewRender(response);
},
function(){
previewError();
}
);
/*_public methods*/
return{
/*make a request*/
previewRequest: function(request){
myRequestManager.require(request); //err:myRequestManager.require is not a func
},
previewRender: function(response){
//do something
},
previewError: function(){
//manage error
}
};
}());
This is the ‘class’ that make the request to the server
function RequestManager(params, success, error){
//create an ajax manager
this.param = params;
this._success = success; //callbacks
this._error = error;
}
RequestManager.prototype = {
require: function(text){
//make an ajax request
},
otherFunc: function(){
//do other things
}
}
The problem is that i can’t call myRequestManager.require from inside singleton object. Firebug consolle says: “myRequestManager.require is not a function”, but i don’t understand where the problem is.
Is there a better solution for implement this situation?
Your code’s in the order you quoted it, isn’t it? The singleton appears above the
RequestManagerin the source?If so, that’s your problem. It’s fairly subtle(!), but assuming your two bits of quoted code are in the order you’ve shown them, here’s the order in which things happen (I’ll explain it more below):
RequestManageris defined.RequestManager.RequestManagerprototype is replaced with a new one.Since the
myRequestManagerinstance was instantiated before the prototype was changed, it doesn’t have the functions you defined on that (new) prototype. It continues to use the prototype object that was in place when it was instantiated.You can fix this easily by re-ordering the code, or by adding properties to
RequestManager‘s prototype rather than replacing it, e.g.:That works because you haven’t replaced the prototype object, you’ve just added to it.
myRequestManagersees the additions because you’ve added them to the object it’s using (rather that setting a new object on the constructor function’sprototypeproperty).Why this happens is a bit technical and I’ll mostly defer to the spec. When the interpreter enters a new “execution context” (e.g., a function, or the global — e.g., page-level — context), the order in which it does things is not strict top-down source order, there are phases. One of the first phases is to instantiate all of the functions defined in the context; that happens before any step-by-step code is executed. Details in all their glory in sections 10.4.1 (global code), 10.4.3 (function code) and 10.5 (declaration bindings) in the spec, but basically, the functions are created before the first line of step-by-step code. 🙂
This is easiest to see with an isolated test example:
As you can see if you run it,
User1fails because theThing1instance it’s using doesn’t have afooproperty (because the prototype was replaced), butUser2works because theThing2instance it uses *does (because the prototype was augmented, not replaced).