Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript object, self reference problem

I just started using oop in javascript and I ran across some problems trying to acces a method from inside another method.

here's the code I had:

var Game = {
initialize: function () {
    if (canvas.isSupported()) {
        sprites[0] = new Player();

        this.update();
    }
},

update: function() {
    for (var i = 0; i < sprites.length; i++) {
        sprites[i].update();
    }

    this.draw();
},

draw: function() {
    this.clear();

    for (var i = 0; i < sprites.length; i++) {
        sprites[i].draw();
    }

    setTimeout(this.update, 10);
},

clear: function() {
    canvas.context.clearRect(0, 0, canvas.element.width, canvas.element.height);
}

}

but calling the Game.update() gives an error that the draw method isn't defined. I couldn't find a real solution for this. eventually I found this How to call a method inside a javascript object where the answer seems to be that I need to safe the this reference like: var _this = this; but I couldn't get that to work in literal notation, so I changed the code to object constructor (I guess that's how it's called) and added the variable.

I then changed

this.draw();

to

_this.draw();

and it worked.

though the

this.clear();

and the this.update() are still the same, they never seemed to give errors in the first place.

Can anyone explain why this is? and maybe point me to a better solution? thanks in advance.

update

Here's what it should be:

var Game = function () {
var _this = this;

this.initialize = function () {
    if (canvas.isSupported()) {
        sprites[0] = new Player();

        this.update();
    }
}

this.update = function () {
    for (var i = 0; i < sprites.length; i++) {
        sprites[i].update();
    }

    this.draw();
}

this.draw = function () {
    this.clear();

    for (var i = 0; i < sprites.length; i++) {
        sprites[i].draw();
    }


    setTimeout(function () { _this.update(); }, 10);
}

this.clear = function () {
    canvas.context.clearRect(0, 0, canvas.element.width, canvas.element.height);
}

}

like image 345
Restart Avatar asked Mar 17 '11 13:03

Restart


1 Answers

When you do this:

setTimeout(this.update, 10);

that does correctly pass the reference to your "update" function to the system, but when the browser actually calls the function later, it will have no idea what this is supposed to be. What you can do instead is the following:

var me = this;
setTimeout(function() { me.update(); }, 10);

That will ensure that when "update" is called, it will be called with this set correctly as a reference to your object.

Unlike some other languages, the fact that a function is defined initially as a property of an object does not intrinsically bind the function to that object. In the same way that if you had an object with a propertly that's a simple number:

   maxLength: 25,

well the value "25" won't have anything in particular to do with the object; it's just a value. In JavaScript, functions are just values too. Thus it's incumbent upon the programmer to make sure that this will be set to something appropriate whenever a function is called in some "special" way.

like image 124
Pointy Avatar answered Oct 03 '22 19:10

Pointy