2009-11-18 3 views
0

J'écris un jeu en ligne qui permet à un utilisateur de progresser d'un puzzle à l'autre, et si l'utilisateur fait des erreurs, chaque puzzle a un bouton de démarrage pour permettre à l'utilisateur de commencer ce casse-tête. Une version simplifiée de la structure du code est ci-dessous:Pourquoi "ceci" ne se met-il pas à jour pour faire référence à un nouvel objet?

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}); 

Le problème que j'ai est que si l'utilisateur a progressé au deuxième puzzle, si elles cliquez sur Démarrer dessus charge le premier casse-tête plutôt que le second. Après un peu de débogage, j'ai calculé que 'ceci', lorsqu'il est utilisé dans les méthodes par le deuxième casse-tête, contient pour une raison quelconque une référence au premier casse-tête, mais 'window.thePuzzle' - qui devrait être le même que - se réfère correctement au deuxième casse-tête.

Pourquoi «ceci» persiste-t-il à se référer au premier?

Permettez-moi de savoir si vous avez besoin de plus d'exemples de code

+1

Une grande partie de cette réponse dépend de ce qui est dans "recommencer" – cwallenpoole

Répondre

1

$ ('# Startover') cliquez sur (this.empty).

Vous avez pris la méthode empty et détacha de this passer en fonction non liée à jQuery ordinaire. Quand il est rappelé, il n'aura aucune référence à la valeur d'origine de this. En fait, lorsqu'une fonction est appelée unbound, this se référera à window, donc vous gribouillerez ce que vous pensez être des propriétés sur les globals.

JavaScript ne lie pas les méthodes de la même manière que les autres langues. Voir par exemple. this answer pour une explication de ce qu'il fait réellement. Cela confond beaucoup de gens; Personnellement, je le considère comme l'un des pires défauts de JavaScript.

+1

C'est un peu ce que je m'attendais à ce que ce soit, mais j'ai vérifié en utilisant console.log et 'this', dans ce contexte spécifique, en quelque sorte encore se réfère à l'ancienne version de window.thePuzzle – wheresrhys

+1

Il n'y a toujours pas assez de code pour reproduire le problème, mais mon soupçon serait quelque part dans le code que vous avez utilisé, vous utilisez 'window.thePuzzle' dans le code qui est appelé par le' le constructeur de puzzle, comme 'init' ou' addListeners'. À ce stade, le code 'puzzleSequence' qui dit' window.thePuzzle = new puzzle' n'aura pas encore écrit le nouvel objet 'window.thePuzzle' - il ne le peut pas, jusqu'à ce que le constructeur ait fini d'exécuter. – bobince

0

Il existe une très bonne (et claire) description de la façon exacte dont la référence this est traitée dans différents contextes à Quirksmode.

Questions connexes