0

So I have this Javascript function (class):

function Test() {
    this.a = function() { return 'hello'; }
    this.b = function() { alert(this.a()); }
    window.onload = this.b;
}
test = new Test();

The code does not work, because the function this.b on window load becomes a global function (outside of the Test function/class) where this.a does not exist.

Something like this:

function Test() {
    this.a = function() { return 'hello'; }
    this.b = function() { alert(test.a()); } // changed this to test
    window.onload = this.b;
}
test = new Test();

does work, but it assumes I know which variable holds the Test function/class which loses the functionality of creating multiple classes.

What is the best solution to maintain this approach (using this pointers inside function/class) and get the wanted result?

user616396
  • 35
  • 8
  • 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) -- especially see the part *Common problem: Using object methods as callbacks / event handlers*. – Felix Kling Jan 31 '14 at 10:25

3 Answers3

5

Actually, it has nothing to do with scope and everything to do with context.

See, when an event handler is called, this is set to whatever element the event is bound to. In this case, this is window.

Try something like this:

function Test() {
    var self = this;
    self.a = function() {return 'hello';};
    self.b = function() {alert(self.a());};
    window.onload = self.b;
}

By "saving" the context to a variable self, you avoid context problems.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
3

in your code this refers to the local function function() { alert(this.a()); }, if you want to refer to the "class scope" you have to store a refence to the class :

function Test() {
    var localTest = this;
    this.a = function() { return 'hello'; }
    this.b = function() { alert(localTest.a()); }
    window.onload = this.b;
}
test = new Test();
markcial
  • 9,041
  • 4
  • 31
  • 41
  • I'm not 100% sure what you mean by *"in your code this refers to the local `function function() { alert(this.a()); }`"* (what refers to the function? Did you mean `this`?), but I think it's wrong. – Felix Kling Jan 31 '14 at 10:29
  • the this refers to local context, not the class context, so when you call the function, the object calling the funcion has the this scope, so you have to store a reference to the outern class – markcial Jan 31 '14 at 10:33
  • 1
    Yeah, that makes more sense (but you really should format `this` as code). But that's not what you have written in your answer. You wrote it so that it can be easily understood as that `this` refers to `function() {...}` (which would be wrong). – Felix Kling Jan 31 '14 at 10:36
3

Try

window.onload = this.b.bind(this)

When you write someObj.func in javascript, the resulting reference has no idea of someObj. Therefore, if you need the correct this in func, you have to provide it explicitly.

This can be done by closing this in the func's parent scope, as other answers suggest, but bind is more transparent in my opinion.

georg
  • 211,518
  • 52
  • 313
  • 390
  • 1
    `.bind()` is not cross-browser, unfortunately. – Niet the Dark Absol Jan 31 '14 at 10:40
  • @NiettheDarkAbsol this is why i didn't knew about that. but when it will be fully supported will be nice. Support table at the end of the page linked [Mozilla docs about bind function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) – markcial Jan 31 '14 at 10:43
  • @NiettheDarkAbsol: No, but there are polyfills available. Have a look at the MDN documentation. – Felix Kling Jan 31 '14 at 11:15