Module/prototype and multiple instances-Collection of common programming errors
I’m trying to get a grip on “OOP” JavaScript techniques, and I began writing a small test application today. Basically, it’s a game loop and on each update coordinates are to be increased so that an HTML element moves.
The problem is I want to be able to run more than one instance of the app, and therefore I’m trying to store the instance data in this
, but what is saved in my constructor and exec()
method is not available in the private update()
method. What seems to be the officer, problem?
var Jsloth = (function () {
var Jsloth = function () {
var sloth = document.createElement('div');
var attr = document.createAttribute('class');
attr.value = 'sloth';
sloth.setAttributeNode(attr);
this.sloth = document.getElementsByTagName('body')[0].appendChild(sloth);
};
var exec = function () {
this.x = 0;
this.y = 0;
var that = this;
setInterval(function () {
that.update();
}, 1000/10);
};
var update = function () {
this.x++;
this.y++;
this.sloth.style.left = this.x + 'px';
this.sloth.style.bottom = this.y + 'px';
};
Jsloth.prototype.constructor = Jsloth;
Jsloth.prototype.exec = exec;
Jsloth.prototype.update = update;
return Jsloth;
})();
var sloth1 = new Jsloth();
sloth1.exec();
Edit: Updated code with a working solution!
-
You’ve not added
update
to the prototype. The value ofthis
in that method will be most likely thewindow
object.Change your call from this:
update();
To this:
update.call(this);
Or add
update
to the.prototype
:Jsloth.prototype.update = update;
and use:
this.update();
But if you’re going to call
update()
from thesetInterval()
, you’ll need to ensure the properthis
value.To do that, you can pass an anonymous function, and keep a reference to the outer
this
value in a variable.var exec = function () { this.x = 0; this.y = 0; var that = this; setInterval(function() { that.update(); //update.call(that); // if you didn't add update() to the .prototype }, 1000/10); };
-
In JavaScript,
this
is (almost) entirely decided by how you call a function, not where/how it’s defined.The way you’re calling
update
:update();
…
this
will be the global object (window
on browsers), orundefined
if you use"use strict"
.To set
this
withinupdate
, usecall
orapply
:update.call(this); // or update.apply(this);
More (on my blog):
- Mythical methods
- You must remember
this
Originally posted 2013-11-09 23:38:21.