admin管理员组

文章数量:1226131

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);
}

}

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);
}

}

Share Improve this question edited May 23, 2017 at 12:22 CommunityBot 11 silver badge asked Mar 17, 2011 at 13:26 RestartRestart 3322 gold badges4 silver badges14 bronze badges 2
  • Could you show the complete code that worked? – Matt Ball Commented Mar 17, 2011 at 13:30
  • 3 +1 for being awesome and posting your update. This post finally concreted the differences in alternate namespacing methods. You made me a better coder today. :) – dano Commented Nov 16, 2012 at 6:26
Add a comment  | 

2 Answers 2

Reset to default 14

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.

You problem is that you use an object literal instead of an instantiated object

Try to do it this way instead:

var Game = function() {
  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(this.update, 10);
  };

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

now use:

 var myGame = new Game();

本文标签: oopjavascript objectself reference problemStack Overflow