6

Well, this doesn't really refer to the wrong object, but I do not know how to refer to the correct one.

function someObj() {
   this.someMethod1 = function() {
      var elementBtn = document.getElementById('myBtn');
      elementBtn.onclick = function() { 
         this.someMethod2(); //I want this.someMethod2() to be called
         //...but it tries to call elementBtn.someMethod2() i believe.
      };
   };
   this.someMethod2 = function() {
      alert('OK');
   };
}

So when my myBtn is clicked I want someObj.someMethod2() to run. And I want it to be that someObj, not any other someObj. But how?!

Neuron
  • 5,141
  • 5
  • 38
  • 59
lejahmie
  • 17,938
  • 16
  • 54
  • 77

3 Answers3

8

You might need to make a tweak like this:

function someObj() {
    var that = this;

    this.someMethod1 = function() {
        var elementBtn = document.getElementById('myBtn');
        elementBtn.onclick = function() { 
            that.someMethod2();
        };
    };
    this.someMethod2 = function() {
       alert('OK');
    };
}

"that" captures the scope you are after.

Juho Vepsäläinen
  • 26,573
  • 12
  • 79
  • 105
  • Well thanks alot, that did solve the problem, but it seems like a kind of nasty solution?! Is there no way to do this any other way? – lejahmie Feb 07 '12 at 09:05
  • 1
    Well, you could return the methods within an object (method this points to the object then) and then bind "this" of that function. More info about bind, https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind . – Juho Vepsäläinen Feb 07 '12 at 09:22
4

The function keyword changes scope. One solution is to maintain the reference to the "this" that you want to use.

Try the following:

function someObj() {
   var self = this;
   this.someMethod1 = function() {
      var elementBtn = document.getElementById('myBtn');
      elementBtn.onclick = function() { 
         self.someMethod2(); //NOTE self
      };
   };
   this.someMethod2 = function() {
      alert('OK');
   };
}
Gazler
  • 83,029
  • 18
  • 279
  • 245
-1

You could use coffee script, which has a fat arrow (used for onclick function) to deal with this kind of thing, and compiles to well formed javascript. By using fat arrow, coffee script ensures the same scope as the function is defined in will be used in the callback function.

play with code here

Coffee Script

someObj = () ->
   @someMethod1 = () ->
      elementBtn = document.getElementById 'myBtn'
      elementBtn.onclick = () => 
         @someMethod2()
   this.someMethod2 = () ->
      alert 'OK'

JavaScript

var someObj;
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
someObj = function() {
  this.someMethod1 = function() {
    var elementBtn;
    elementBtn = document.getElementById('myBtn');
    return elementBtn.onclick = __bind(function() {
      return this.someMethod2();
    }, this);
  };
  return this.someMethod2 = function() {
    return alert('OK');
  };
};
Billy Moon
  • 57,113
  • 24
  • 136
  • 237
  • But I don't want to use CoffeeScript. –  Feb 11 '16 at 15:51
  • 1
    @torazaburo it's ok, you don't have to use coffee-script. However, even without using it directly, you can still learn from the patterns in it's design (which have heavily influenced es6 btw). In this case, the pattern of retaining the current context in a called function which coffee-script has a fat arrow syntax for is revealed in the generated javascript. Coffee-script's method of doing this, is a general solution, and tried and tested. By examining the output javascript, it is possible to understand the answer to the original question - even if you hate coffee-script. – Billy Moon Feb 11 '16 at 16:05