2

I have JS code roughly like this:

function myObject()
{
    this.a = 13;

    this.fetchData = function()
    {
        alert(this.a);
        getData(this.processData);
    }

    this.processData = function(data)
    {
        // do stuff with data
        alert(this.a);
    }

    this.fetchData();
}

function getData(callback)
{
    // do async request for data and call callback with the result
}

My problem is: The function fetchData has access to my a variable via the this keyword, but the other function processData does not when called by getData. I understand why this happens, but don't know how to work around it.

How would you approach this problem preferably in OOP style? (The function getData has to be available to multiple classes)

2 Answers 2

3

Two options:

1) Have getData accept a context parameter (usually called context or thisArg) and use callback.apply(context, ...) or callback.call(context, ...) to call it. So:

function getData(callback, context) {
    // ...when it's time to call it:
    callback.call(context, arg1, arg2);
    // or
    callback.apply(context, [arg1, arg2]);
}

2) Create a function that, when called, will turn around and call the original callback with this set to the correct value. (This is sometimes called "binding".)

For example, using an explicit closure:

this.fetchData = function()
{
    var self = this;

    alert(this.a);
    getData(getDataCallback);

    function getDataCallback(arg1, arg2) {
        self.processData(arg1, arg2);
    }
}

Or have a generic bind function to do it (which will also involve a closure, but in a nice controlled context so it's not closing over stuff you don't need). See link below for an example of a simple bind function.

More: You must remember this

Sign up to request clarification or add additional context in comments.

4 Comments

+1: for option 2, you would call getData(function(){ this.processData(); }); instead of getData(thisProcessData);
@Eric: No, that won't work. this is defined entirely by how a function is called, not where it's defined. Your getData(function(){ this.processData(); }); would have exactly the same problem as getData(this.processData); You can, though, use a closure (I've added a closure example).
@T.J. Crowder: of course, you're right. Thanks for adding the example.
BTW: does jQuery have a built-in binding function for doing this?
0

I think that you only need to define "a" as a local variable so that it is in the cope of both fetchData and getData, something like this:

function myObject() {
   var a = 13;

   this.fetchData = function() {
      alert(a);
      getData(this.processData);
   }

   this.processData = function(data) {
      // do stuff with data
      alert(a);
   }

   this.fetchData();
}

You could also do,

function myObject() {
   this.a = 13;
   var that = this;

   this.fetchData = function() {
      alert(that.a);
      getData(this.processData);
   }

   this.processData = function(data) {
      // do stuff with data
      alert(that.a);
   }

   this.fetchData();
}

1 Comment

+1 for setting a in private scope of closures fetchData and processData.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.