2009-11-10 3 views
14

J'espère que quelqu'un pourra m'expliquer pourquoi le code JavaScript/HTML ci-dessous affichera "porte # 2" lorsque le code HTML est affiché dans un navigateur:Référencer une valeur JavaScript avant qu'elle ne soit déclarée - Quelqu'un peut-il expliquer cela?

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
    <script type="text/javascript"> 
     function testprint() { 
      alert('door #1'); 
     }; 

     window.onload = testprint; 

     function testprint() { 
      alert('door #2'); 
     }; 

     testprint = function() { 
      alert('door #3'); 
     }; 
    </script> 
    <script type="text/javascript"> 
     function testprint() { 
      alert('door #4'); 
     }; 
    </script> 
</head> 
<body> 
</body> 
</html> 

Depuis que la déclaration testprint se produit avant window.onload est réglé sur testprint, je me attends window.onload cause « porte # 1 » à se manifester. En fait, onload provoque la porte n ° 2. Notez qu'il le fera si la première déclaration de testprint est incluse ou non.

La troisième et la quatrième déclaration de testprint utiliser différents moyens d'attribution de la fonction, j'ai essayé ceci pour voir si elle l'emporterait sur le comportement de window.onload dans le même était la deuxième déclaration de testprint fait. Il n'a pas. Notez que si je déplace la quatrième déclaration de testprint à la fin du premier bloc de script, elle sera appelée par window.onload.

Répondre

38

déclarations de fonction font l'objet de levage, et ils sont évalués au moment de l'analyse, par levage signifie qu'ils sont disponibles pour l'ensemble du périmètre dans lequel ils ont été déclarés, par exemple:

foo(); // alerts foo 
foo = function() { alert('bar')}; 
function foo() { alert('foo');} 
foo(); // alerts bar 

Le premier appel à foo exécutera la déclaration de fonction , car à Parse temps il a été mis à la disposition, le deuxième appel de foo exécutera l'expression de la fonction , a déclaré à exécution.

Pour une discussion plus détaillée sur les différences entre les expressions de fonction et les déclarations de fonction, vérifiez this question et this article.

+0

Il y a une subtilité à la fonction de levage où [les navigateurs ne sont pas d'accord] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope#Conditionally_defining_a_function). _SpiderMonkey_ ** ** ne va pas lever les fonctions déclarées dans une portée conditionnelle alors que _V8_ (au moment de l'écriture) le fait. –

-1

La fonction testprint est globale à la page. le testprint = function ... assigne une variable, dont je ne suis pas sûr exactement de la portée entière, mais j'ai l'impression qu'elle n'est pas ajoutée au dictionnaire de la table des fonctions comme le premier.

0

La raison # 3 ne change pas window.onload est que les fonctions sont appelées par référence, pas par le nom. Lorsque vous définissez window.onload = testprint, il attribue une référence à la valeur actuelle de testprint (porte n ° 2, comme expliqué par CMS) à window.onload. La modification ultérieure de la valeur de testprint n'affecte pas la valeur de window.onload. La porte n ° 4 ne remplace pas la porte n ° 2 (à moins que, comme vous l'avez dit, vous le déplaciez dans le premier bloc de script) car elle se trouve dans un bloc de script différent, elle est analysée après la fin du premier bloc.

Questions connexes