2011-06-09 5 views
2

J'ai remarqué quelque chose que je ne peux pas tout à fait expliquer. J'ai fait ce code javascript qui pousse ou réduit une boîte bleue. Le script est ici:Javascript setInterval question

var animated = { 

    timer : null, 

    el : document.getElementById("divNavyBox"), 

    startGrowAnimation : function() { 

     this.stopAnimation(); 

     this.timer = setInterval(

      animated.doAnimation(5), 10); 

    }, 

startShrinkAnimation : function() { 

    this.stopAnimation(); 

    this.timer = setInterval(function() { 

     animated.doAnimation(-5); 

    }, 10); 

}, 

stopAnimation : function() { 

    clearInterval(this.timer); 

}, 

doAnimation : function(amount) { 

    var size = this.el.offsetWidth; 



    if ((amount > 0 && size < 200) || (amount < 0 && size > 0)) { 

     this.el.style.width = size + amount + "px"; 

     this.el.style.height = size + amount + "px"; 

    } else { 

     this.stopAnimation(); 

    } 

} 

}; 

Lorsque la méthode startGrowAnimation de la classe d'animation est appelée, la boîte jusqu'à ce qu'il pousse visuellement atteint une certaine largeur et la hauteur. Il s'arrête ensuite. Le code startGrowAnimation se trouve ci-dessous:

startGrowAnimation : function() { 
    this.timer = setInterval(function() { 
     animated.doAnimation(5); 
    }, 10); 
} 

Ce code fonctionne très bien. Cependant, je ne comprends pas pourquoi il est nécessaire de mettre une fonction anonyme dans le paramètre au lieu de simplement la fonction d'appel normale. Alors, je l'ai remplacé le code ci-dessus avec le code ci-dessous:

startGrowAnimation : function() { 

    this.stopAnimation(); 

    this.timer = setInterval(animated.doAnimation(5), 10); 

}, 

Lorsque j'utilise ce code, pour une raison quelconque, la boîte ne fait qu'accroître la taille de cinq pixels à chaque fois que la méthode startGrowAnimation est appelée. Alors, pourquoi est-il nécessaire d'inclure la méthode startGrowAnimation dans un appel de fonction anonyme dans ce cas?

+0

+1 - Grande question qui suscite la réflexion! – jmort253

Répondre

4

Le code que vous avez essayé appellera cette fonction et transmettra le retour à setInterval(). Ce n'est évidemment pas ce que vous voulez.

Si vous avez placé animated.doAnimation (une référence à la fonction) comme argument de rappel, la valeur this à l'intérieur de cette fonction pointera vers window, et non l'objet lui-même. C'est parce qu'il a perdu le contexte d'être appelé comme une méthode de cet objet. Vous devez donc appeler la méthode comme propriété de l'objet. Cela signifie que vous devez utiliser un wrapper de fonction anonyme afin que son corps puisse être animated.doAnimation().

La seule autre façon ne vaut pas la peine d'être mentionnée car elle appelle une fonction de type eval().

+0

+1 - Bonne réponse! Et oui, eval ne vaut vraiment pas la peine d'être mentionné. Probablement pas même la peine * mentionner * il ne vaut pas la peine de mentionner. Je suis sûr que quelqu'un va chercher ce que eval fait et essayer de l'utiliser;) – jmort253

+0

Cela explique beaucoup. Cependant, une chose reste qui m'intrigue encore. Vous avez expliqué comment, lorsque ce n'est pas à l'intérieur d'une fonction anonyme, la propriété "this" fait référence à l'objet window au lieu de l'objet désiré. Chaque fois que j'appelle startGrowAnimation sans encapsuler l'instruction doAnimation dans une fonction anonyme, elle augmente toujours de cinq pixels. Il le fait seulement une fois au lieu de continuellement. Cela n'a toujours pas de sens pour moi ... – idungotnosn

+0

@Michael Cela peut être très déroutant :) Ce qui se passe, c'est que vous appelez * la fonction, ** mais pas ** une référence à celle-ci. Sa valeur de retour est passée comme premier argument ('undefined' dans cet exemple) à' setInterval() '. – alex