I'm trying to write OO javascript for an object that has an expensive initialization process that will callback a function when its done.
The problem is that the caller needs to use the functions of that same object in the callback routine, and the object doesn't exist yet:
// ctor for foo object
function foo(callback) {
// do slow initialization here..
// callback when done
callback();
};
foo.prototype = function() {
return {
// doStuff method
doStuff: function() {
alert('stuff done');
}
};
}();
// instantiate the foo object, passing in the callback
var f = new foo(function() {
//Uncaught TypeError: Cannot call method 'doStuff' of undefined
f.doStuff();
});
jsFiddle What am I missing here?
It should be a simple fix. First, make sure your callback is called with the this
object set to the current object
function foo(callback) {
// do slow initialization here..
callback.call(this);
};
Then adjust how you make your callback
var f = new foo(function() {
this.doStuff();
});
Here's your updated fiddle
Here's why it doesn't work: when JavaScript is executing the code, before it can set f
, it needs to evaluate the new foo(...)
expression. Inside of the constructor, it calls the callback. JavaScript still has not set f
since the expression has not yet finished. As soon as the constructor finishes, f
is set correctly, but it never gets there because you try to use f
inside of the callback when it is still undefined
.
You could call the callback on the next iteration through the event loop, so rather than:
callback();
You'd do:
setTimeout(callback, 0);
This would only work if you're already assuming that it completes asynchronously, though.
Your approach is the intrinsic issue. Define doStuff within the constructor. The call as such:
var f = new Foo();
f.doStuff();
You can also create an init method to run whenever a new object is created. But, you should do this within the scope of the constructor... do not pass a callback to a constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With