Because you didn't use an arrow function to preserve the execution context that the keyword this
points to, so once the function that you're making setTimeout/setInterval call gets triggered, this
will be the global scope.
(if you're running this in the browser, this
will be window
by the time the timeout/interval resolves. You can verify that by doing a console.log(this)
in your code).
If you need this
to stay the same, use an arrow function to make sure that this
keeps pointing at what it's pointing to when you declare the code, rather than when the code executes: setInterval(() => this.timeForward(), 500)
.
Also, modern browsers support modern JS, with consts and class syntax, so what you're doing in a function may make more sense written as:
class Universe() {
constructor() {
this.timer = 0;
this.tick = 0;
}
timeStart(){
this.timer = setInterval(() => this.timeForward(), 500);
}
timeStop() {
if (this.timer) {
clearInterval(this.timer);
}
}
timeForward() {
this.tick++;
console.log(this.tick);
}
}
const universe = new Universe();
universe.timeStart();
And then loading that with a <script src="yourfile.js" defer></script>
, where the defer
keyword basically does the same thing that jQuery's $(...)
does: it runs the code in your file only after the DOM is done (but before DOMContentLoaded gets triggered), no matter where in the HTML you place that script tag.