Déclaration de fonction ambiguë dans Javascript

Je suis nouveau sur Javascript et j'ai été confondu par la fonction de la déclaration de fonction. J'ai fait un test à ce sujet et obtenu des résultats intéressants:

say(); function say() { alert("say"); } 

La déclaration directe a fonctionné et popup "say"

Au contraire

 say(); say = function() { alert("say"); } 

N'a pas fonctionné, bien qu'il ait également déclaré un objet de fonction

Si nous déclarons la fonction et redécouvrons cela après:

 function say() { alert("speak"); } say(); function say() { alert("say"); } 

J'ai «dit» au lieu de «parler». C'est une surprise!

D'ACCORD. Il semble que seule la dernière déclaration de fonction fonctionne. Ensuite, nous allons déclarer l'objet fonction d'abord, puis une fonction "régulière":

 say = function() { alert("speak"); } say(); function say() { alert("say"); } say(); 

Une autre surprise, c'était "parler" suivi de "parler". La déclaration de fonction "régulière" n'a pas fonctionné du tout!

Y a-t-il une explication de tous? Et si la déclaration de fonction "régulière" est vraiment "fragile" et peut être facilement remplacée par l'objet de fonction avec le même nom, puis-je m'arrêter de cela?

Une autre question est: avec seulement le format d'objet fonction, cette déclaration directe devient-elle impossible? Existe-t-il un moyen de "simuler" que dans Javascript?

Javascript fonctionne comme ceci:

Le document est analysé et les déclarations de function sont prises en compte immédiatement, avant l'exécution des déclarations réelles. Cela explique votre premier exemple.

Si vous affectez une fonction à une variable locale, cela se fait pendant l'exécution, vous ne pouvez donc pas utiliser la méthode dans votre deuxième exemple.

Ce que vous ressentez, c'est que si vous déclarez une fonction deux fois, la dernière sera utilisée par l'application entière. C'est votre troisième exemple.

Ces fonctions sont constituées membres de l'objet window , elles sont effectivement déclarées globalement. Si vous affectez une variable locale à une valeur d'une fonction, cette variable locale a priorité sur les membres dans l'objet de window . Si javascript ne parvient pas à trouver une variable locale, il recherche la portée, l'objet de la window étant le dernier recours. C'est ce qui s'est passé dans votre dernier exemple, mais il a une variable qui est dans une portée plus spécifique que la fonction globale.

Si vous désirez say en cours d'exécution, c.-à-d. Permuter l'ordre des déclarations dans votre dernier exemple, vous verriez les deux alertes différentes que vous attendez:

 say(); //speak, the global function function say() { alert('speak'); } var say = function() { alert('say'); } say(); //say, the declared local variable 
 say(); function say() { alert("say"); } 

Ici, l'interprète récupère la définition de say() lorsqu'il est appelé et l'exécute.

 say(); say = function() { alert("say"); } 

Ici, il n'y a pas de définition de say() to fetch – mais vous assignez une fonction anonyme à une variable. L'interprète ne peut pas "trouver" cela comme s'il-même peut trouver des déclarations avancées.

 function say() { alert("speak"); } say(); function say() { alert("say"); } 

Ici say est défini et redéfini – la dernière définition gagne.

 say = function() { alert("speak"); } say(); function say() { alert("say"); } say(); 

Voici une variable indiquant une fonction anonyme (après que la première déclaration est interprétée). Cela a priorité sur toute définition de fonction, comme si vous aviez placé la définition de fonction avant l'affectation.

Mais si vous aviez

 say(); say = function() { alert("speak"); } say(); function say() { alert("say"); } 

Ensuite, vous obtiendrez "dire" suivi de "parler".

Vous pouvez vous attendre à ce que vos définitions de fonction soient appliquées dans l'ordre. Ensuite, toutes vos lignes de code non-méthode seront exécutées dans l'ordre, y compris l'affectation des objets fonctionnels. Cela explique chacun de vos exemples. C'est pourtant un problème intéressant. Vous ne pouvez vraiment pas assigner un objet fonction après avoir essayé de l'appeler, et vous attendez à ce qu'il fonctionne. Cependant, une définition de fonction qui suit le code exécutable sera effectivement appliquée en premier.

C'est toujours une bonne idée d'appeler la fonction plus tard, même si javascript fonctionne comme ça.

La plupart des langues ne fonctionneront pas de cette façon, au lieu de cela.

 function say(){ alert("say"); } say(); 

ou

 say = function(){ alert("say"); } say(); 

ou

 (function(){ alert("say"); })();