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
updateto the prototype. The value ofthisin that method will be most likely thewindowobject.Change your call from this:
update();To this:
update.call(this);Or add
updateto 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 properthisvalue.To do that, you can pass an anonymous function, and keep a reference to the outer
thisvalue 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,
thisis (almost) entirely decided by how you call a function, not where/how it’s defined.The way you’re calling
update:update();…
thiswill be the global object (windowon browsers), orundefinedif you use"use strict".To set
thiswithinupdate, usecallorapply: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.