1

When test.testHello(helloWorld.sayHello); runs, it doesn't recognize that I have inserted a new greeting is the greeting is undefined. I can use bind to make sure it runs it in the proper scope, I am not really sure why isn't it running in the proper scope to begin with. Could someone explain why this is happening and show me a better solution?

Solution: test.testHello(helloWorld.sayHello.bind(helloWorld));

http://jsfiddle.net/EzabX/

var HelloWorldClass = function() {


 this.greetings = [];
}
HelloWorldClass.prototype.addGreeting = function(greeting) {
    this.greetings.push(greeting);
}
HelloWorldClass.prototype.sayHello = function() {
    document.getElementById('output').innerHTML += this.greetings;
    this.greetings.forEach(function(greeting) {
        greeting.execute();        
    })
}

var TestClass = function() {
    this.testHello = function(callback) {
        alert("TestHello is working, now callback");
        callback();
    }
}


var main = function() {
    var helloWorld = new HelloWorldClass();
    var test = new TestClass();
    helloWorld.addGreeting({
        execute: function() {
            alert("Konichiwa!");
        }
    });
    helloWorld.sayHello();

    test.testHello(helloWorld.sayHello);
}

main();
Strawberry
  • 66,024
  • 56
  • 149
  • 197
  • 2
    what scope are you talking about ? – Vinz243 Mar 01 '14 at 11:09
  • Another way to think about it is `this` isnt a reference to construction context/scope. It's a reference to the *invoker* of a function. Who or what is invoking `callback`? Not `helloWorld`. `bind` gives you a function where the invoker is stable – J. Holmes Mar 01 '14 at 12:59

1 Answers1

0

Managing the this variable within the prototype function scope when called as a callback can be complicated for novice users. You don't always need a prototype for all functions on a class. If you really want to use a prototype function look at Javascript .bind(this) implementations. Google and Stackoverflow are your friend on that topic. Example: Preserving a reference to "this" in JavaScript prototype functions

Offending code with this referring to DOM Window object and not a HelloWorld instance:

this.greetings.forEach(function(greeting) {
        greeting.execute();        
    })

A non-prototype version that works just great, easy to use. Fiddle: http://jsfiddle.net/EzabX/2/

var HelloWorldClass = function() {
    var greetings = [];

    this.greetings = greetings;

    this.addGreeting = function(greeting) {
        greetings.push(greeting);
    };

    this.sayHello = function() {
        document.getElementById('output').innerHTML += greetings;
        greetings.forEach(function(greeting) {
        greeting.execute();        
        })
    }; }
Community
  • 1
  • 1
Ted Johnson
  • 4,315
  • 3
  • 29
  • 31
  • There's nothing wrong with the `greetings`. What exactly do you think is offending in that snippet? – Bergi Mar 01 '14 at 12:00
  • 'this' refers to Window and not HelloWorld. Not sure how a working answer and the correct links to other working answer is down voted. Tweaked the offending line. – Ted Johnson Mar 01 '14 at 12:05
  • In the `helloWorld.addGreeting(…)` call, `this` *does* refer to `helloWorld`. I didn't downvote because of the link, but because of wrong terms ("scope"), wrong explanation, and hardly helpful code suggestion. – Bergi Mar 01 '14 at 12:15
  • Inside the forEach callback? Yes, but `this` is not used there, only `greeting`. – Bergi Mar 01 '14 at 12:39
  • Oh wait, you refer to the `sayHello` call… Yeah, there it doesn't work, but your example code doesn't either. – Bergi Mar 01 '14 at 12:40
  • It makes the third call in JSfiddle using sayHelloa, just checked in the chrome debugger again. I have fixed the scope word, yup that was just a typo from rewriting a sentence too quickly. – Ted Johnson Mar 01 '14 at 12:42
  • Yeah, but you're still using `this.greetings` which resolves to `undefined` – Bergi Mar 01 '14 at 12:45
  • Are you looking at: http://jsfiddle.net/EzabX/1/ ? I am assigning it, but not using it. I am using a locally scoped variable within the 'constructor'. Also fixed formatting to make it more clear in the stack answer. – Ted Johnson Mar 01 '14 at 12:50
  • Yes I do, it's outputting `undefined` into the `innerHTML` – Bergi Mar 01 '14 at 12:51
  • What is that line meant to do anyhow? I agree with your point but the question was around the callback? I have at least removed the `this`. Thanks. – Ted Johnson Mar 01 '14 at 12:54