0

I am a proficient c# programmer, and I have a little bit of experience with HTML and Javascript, but I can't seem to figure out objects.

I am attempting to create a loop, which just keeps updating until the counter reaches 5 then stops the loop. but in the Update method counter = NaN.

This is my exact code.

function LoginScreen() {
    this.IntervalID = null;
    this.counter = 0;

    this.Start = function () {
        this.IntervalID = setInterval(this.Update, 60 / 1000);
    };

    this.Stop = function () {
        clearInterval(this.IntervalID);
    };

    this.Update = function () {

        this.counter++;
        alert(this.counter);

        if (this.counter > 5) this.Stop();
    };

}

LS = new LoginScreen();
LS.Start();
2
  • Are you trying to loop every minute? If so, check the setInterval() parameter. Commented Oct 16, 2013 at 9:06
  • I doesn't matter how often it loops, my interval is actually 60 times a second but not relevant to this question at this time Commented Oct 16, 2013 at 9:08

3 Answers 3

3

The problem is scope of the inner this of your Start(), Stop() and Update() functions. Within those functions, this is referring to the function, and not your LoginScreen object.

To get around these problems, I like to use a little self variable to help with scope issues. That way, whatever is referring to the self variable will use the object. Here's what I mean:

function LoginScreen() {

    // add this for scope fun...
    var self = this;

    this.IntervalID = null;
    this.counter = 0;

    this.Start = function () {
        self.IntervalID = setInterval(self.Update, 60 / 1000); // updated...
    };

    this.Stop = function () {
        clearInterval(self.IntervalID); // updated...
    };

    this.Update = function () {
        self.counter++; // updated...
        alert(self.counter); // updated...

        if (self.counter > 5) self.Stop(); // updated...
    };
}

LS = new LoginScreen();
LS.Start();

Hope this makes sense!

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

3 Comments

WoW.... it does make sense, but... WoW... who designed this. I see my head is going to hurt trying to learn javascript after c#. Is this really the accepted way of doing this?
The "looseness" of scope is something I both appreciate and cry over in JavaScript...good luck, and keep learning! ;)
JavaScript is a love/hate relationship. You get used to it. :)
2

You ran into the dreaded Javascript "this" problem.

Try changing your this.Update code to:

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

        self.counter++;
        alert(self.counter);

        if (self.counter > 5) self.Stop();
    };

But wait there is more

1 Comment

Good answer but Chris beat you to it
2

This is a very common mistake in Javascript. I think everyone including me did this at one point. It is fairly easy to understand, though.

What's going on

When you call a function as a method of an object, you set its context to the object. That means that this inside this function will point to your context object.

MyObject = {};
MyObject.someValue = 1;

MyObject.myMethod = function() {
    console.log(this.someValue); // This will log "1" to the console, as expected
};

Now comes the tricky part: You can change the context of a function. Let's add some more lines of code here:

MyOtherObject = {};
MyOtherObject.someValue = 2;
MyOtherObject.myMethod = MyObject.myMethod;

When you now call MyOtherObject.myMethod you call the same function as if you would call MyObject.myMethod, but in one case this points to MyObject and in the other case it points to MyOtherObject.

Now, when you call setInterval(MyObject.myMethod, 1000), the functions context will be set to window (technically, setInterval calls window.setInterval) and since window does not have a property called someValue, it will just be undefined.

How to fix it

To fix this, you can create another reference to your LoginScreen object. It will always point to the same object inside the entire scope, unless you change it. You can then use it as an alternative to this without worrying about the context.

function LoginScreen() {
    this.IntervalID = null;
    this.counter = 0;

    // Create another reference to "this"
    var self = this;

    this.Start = function () {
        // The function behind "this.Update" will always be called with "window"
        // as its context.
        this.IntervalID = window.setInterval(this.Update, 60 / 1000);
    };

    this.Stop = function () {
        // This function is called as "self.Stop", therefore "this" points to
        // "self", which points to the right object, so you can use "this".
        clearInterval(this.IntervalID);
    };

    this.Update = function () {
        // Inside this function, "this" points to "window".
        // You therefore have to use the previously declared "self"
        // to point to the right object.
        self.counter++;
        alert(self.counter);

        if (self.counter > 5) self.Stop();
    };

}

LS = new LoginScreen();
LS.Start();

Further reference

this - Mozilla Developer Network Another explanation of the beviour of this in JavaScript, along with some functions to control it.

1 Comment

Wow...super explanation!

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.