Newbie Javascript question

Started by
3 comments, last by Concentrate 10 years, 11 months ago

So I have this javascript code:


var sim = new function()
{
...
...
...
this.Tick = function () 
	{
		var currTime = Date.now();
		var elapsedMS = currTime - this.lastUpdateTime;

		this.Update(elapsedMS);
		this.Render();

		this.lastUpdateTime = currTime;
	};

this.Run = function()
	{
		this.tickIntervalId = setInterval(this.Tick, 1000/60); //Update at 60 fps
	};

Getting the following error: Uncaught ReferenceError: Update is not defined.

Anybody know what's causing this?

J.W.
Advertisement

The problem is right there in the error message: You are calling


this.Update(elapsedMS);

in your this.Tick function, but you have not defined an Update function anywhere.

Oops. I realized that I only posted part of the code I have. Here is more relevant code:


//create singleton class
var sim = new function()
{
...
this.Run = function()
	{
		this.tickIntervalId = setInterval(this.Tick, 1000/60); //Update at 60 fps
	};
...

this.Update = function (elapsedMS) {
		
	  for (var i = 0; i < nodeArr.length; i++) {
		nodeArr.Update();
	  }
	};
...
this.Tick = function () 
	{
		var currTime = Date.now();
		var elapsedMS = currTime - this.lastUpdateTime;

		this.Update(elapsedMS);
		this.Render();

		this.lastUpdateTime = currTime;
	};
};

sim.Run();
J.W.

In JavaScript functions don't really have a "context" associated statically with them, it is evaluated dynamically .. setTimeout and setInterval basically "reset" the context and your call to "this.Tick" doesn't know what "this" is.

Change

this.tickIntervalId = setInterval(this.Tick, 1000/60); //Update at 60 fps
To
this.tickIntervalId = setInterval(function() { this.Tick() }, 1000/60); //Update at 60 fps

To not lose the context
Edit: missing parenthesis on "To" -line's call to Tick()
Another edit:
Actually, not 100% sure of the "this.Tick()" inside that function either, the only sure-fire way to not lose "this" is to define something like var me = this; on the line above and call me.Tick() instead.
I.e.:
var me = this;
this.tickIntervalId = setInterval(function() { me.Tick() }, 1000/ 60);

If you are running on chrome, you can simply use the bind function,


this.tickIntervalId = setInterval(this.Tick.bind(this), 1000/60); //Update at 60 fps

or if you are using the popular underscore utility


this.tickIntervalId = setInterval(_.bind(this.Tick,this), 1000/60); //Update at 60 fps

The problem is that your Tick function gets called in a global context. Which means that, the 'this' pointer is the global 'this' which is not what you need. Hence you need to bind the 'this' context so that when the Tick function gets called from a global context, the original 'this' pointer is still saved.

Edge cases will show your design flaws in your code!
Visit my site
Visit my FaceBook
Visit my github

This topic is closed to new replies.

Advertisement