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