0

After looking through a few different questions regarding this topic, I'm still stumped as to how to access another function from within an object.

window.Think = {
    initialize: function(){
        this.currentNumber = 0;
    },
    updateNumber: function(){
        this.currentNumber += 1;
    },
    listener: function(){
        document.getElementById('foo').addEventListener('click', function(){
        this.parent.updateNumber(); //this is where I want to call the prev function
    }
}

The error I'm getting is Cannot call method 'updateNumber' of undefined

How can I call Think.updateNumber() from within listener()?

stevenspiel
  • 5,775
  • 13
  • 60
  • 89
  • 1
    No, `this` does not reference `window.Think` inside of the event listener callback. Also, FYI, you have a syntax error (missing a `});`at the end of the `listener` method, before the second-to-last "}") – jraede Dec 19 '13 at 01:28
  • In his code, `this.parent.updateNumber();` is in a the function for the `click` event on `#foo`, so `this` would reference that element (if I'm not mistaken), and not `window.Think` – jraede Dec 19 '13 at 01:31
  • 2
    This, people, is why indentation is important. Because of lack of proper indentation, it was totally missed there was a nested callback function. – Alex Wayne Dec 19 '13 at 01:36
  • possible duplicate of [How to access the correct \`this\` / context inside a callback?](http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback) – Felix Kling Dec 19 '13 at 01:36

3 Answers3

5

Callback functions often lose context (context is the value of this). So you have to save the value of this. to a local variable that is shared with the callback function. A common convention for this is var self = this.

listener: function(){
    var self = this;
    document.getElementById('foo').addEventListener('click', function(){
        self.updateNumber();
    }
}
Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
  • 1
    If you're open to CoffeeScript, it has built in functionality for referencing the `this` of the parent function. You define a function with `->`, and a function that retains the previous value of `this` with `=>`. Renders this issue moot. – jraede Dec 19 '13 at 01:29
  • 1
    One of CoffeeScript's best features, but this question is not about CoffeeScript. – Alex Wayne Dec 19 '13 at 01:32
  • @jraede: ES6 arrow functions behave the same way. – Felix Kling Dec 19 '13 at 01:38
  • `this` is not context. It is one variable **within** an execution context, that is, it is associated with an execution context, it is not **the** context. – RobG Dec 19 '13 at 02:01
  • Callback functions never "lose context", though very often programmers do not correctly set the value of `this` when calling a function. – RobG Dec 19 '13 at 02:03
3

this will be rebound to the function's scope. The solution is creating another variable you can refer this to:

listener: function(){
    var that = this;
    document.getElementById('foo').addEventListener('click', function(){
        that.updateNumber();
    });
}

Depending on what browsers you are targeting bind might also be a solution:

listener: function(){
    document.getElementById('foo').addEventListener('click', function(){
        this.updateNumber();
    }.bind(this));
}
TimWolla
  • 31,849
  • 8
  • 63
  • 96
  • @TimWolla `this` has nothing to do with scope, it is set by how a function is called, or `bind`. – RobG Dec 19 '13 at 02:03
2

The problem is that what the keyword "this" represent.

listener: function(){//We call this is function one.
        document.getElementById('foo').addEventListener('click', function(){//function two
        this.parent.updateNumber(); //this is where I want to call the prev function
    }

In function one,"this" represents the object Think.In function two,"this" represents the element foo.So,if you want to call the method updateNumber,you should get the reference to the object Think.We just save the "this" of function one in a variable ,like this:

listener: function(){//We call this is function one.
        var outerThis=this;//save Think here.
        document.getElementById('foo').addEventListener('click', function(){//function two
        outerThis.updateNumber();//use Think.updateNumber here.
    }

Now we get the work done. Because in javascript,the function can access it's outer function's variable,so we can use outerThis in function two.

york
  • 108
  • 8