I’m writing an online game which allows a user to progress from one puzzle to the next, and if the user makes mistakes, each puzzle has a start again button to allow the user to start just that puzzle from scratch. A simplified version of the code’s structure is below:
function puzzle(generator) {
this.init = function() {
this.generator = generator;
...
this.addListeners();
}
//fires when the puzzle is solved
this.completed = function() {
window.theSequence.next();
}
this.empty = function() {
//get rid of all dom elements, all event listeners, and set all object properties to null;
}
this.addListeners = function() {
$('#startOver').click(function() {
window.thePuzzle.empty();
window.thePuzzle.init();
});
}
this.init();
}
function puzzleSequence(sequenceGenerator) {
this.init = function() {
//load the first puzzle
window.thePuzzle = new puzzle({generating json});
}
this.next = function() {
//destroy the last puzzle and create a new one
window.thePuzzle.empty();
window.thePuzzle = new puzzle({2nd generating json});
}
}
window.theSequence = new puzzleSequence({a sequence generator JSON});
The problem I have is that if the user has progressed to the second puzzle, if they click start over it loads the first puzzle rather than the second. After a bit of debugging I’ve worked out that ‘this’, when used in methods by the second puzzle, for some reason still holds a reference to the first puzzle, but ‘window.thePuzzle’ – which should be the same as this – correctly refers to the second puzzle.
Why is ‘this’ persisting in referrring to the first one?
Let me know if you need more code samples
You’ve taken the
emptymethod and detached it fromthisto pass as a plain unbound function to jQuery. When it gets called back, it will have no reference to the original value ofthis. In fact, when a function is called unbound,thiswill refer towindow, so you’ll be scribbling what you think are properties onto the globals.JavaScript doesn’t bind methods in the same way as other languages. See eg. this answer for an explanation of what it actually does. This confuses many people; personally I consider it one of JavaScript’s worst flaws.