Activation Javascript et conflit de nom de formulaire

J'ai une fonction javascript qui ne fonctionnerait pas et je lançais une erreur. Il m'a fallu environ une heure pour me rendre compte que ma forme avait le même nom que la fonction. Il semblait étrange qu'un nom de formulaire soit en conflit avec un nom de fonction, mais je change le nom de toute façon et tout fonctionne bien. Est-ce que quelqu'un sait pourquoi cela se produirait même?

Si vous exécutez ce code, il échouera, mais si vous modifiez le nom du formulaire, il est très étrange.

<html> <head> <title>Untitled Document</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <script type="text/javascript"> function mytest(){alert("hello");} </script> </head> <body> <form name="mytest" ></form> <a href="#" onClick="mytest();">Click Me</a> </body> </html> 

Je l'exécute sur IE6. Ce qui est étrange pour moi, c'est que l'un est le code Javascript et l'autre est un attribut de HTML.

Lien direct où vous pouvez voir ceci se produire:
JSBin

Pour ajouter des détails sur ce qui se passe ici, vous devez comprendre la chaîne de portée de javascript.

Objet de portée

Un objet de portée est un objet caché créé lorsqu'une fonction est exécutée sur laquelle les variables déclarées avec var sont placées en tant que propriétés, aussi toute function nommée à l'intérieur de la fonction d'exécution est également placée en tant que propriétés sur l'objet de portée.

Lorsqu'un identifiant tel que mytest est demandé, javascript recherche ce nom attaché à l'objet de portée actuel (entre autres, l'objet scope est également appelé «contexte d'exécution»).

Chaîne de portée

Lorsqu'une fonction est déclarée dans une fonction, l'objet de portée actuel est attaché à la fonction. Lorsque cette fonction interne s'exécute (et a donc son propre objet de portée), l'exécution du code a accès non seulement à l'objet de portée actuel, mais aussi à l'objet de portée dans lequel la fonction en cours d'exécution a été créée. Arrêtez ici, relisez cette dernière phrase. Ceci est connu sous le nom de chaîne de portée , la chaîne sera aussi profonde qu'il y a des fonctions à l'intérieur des fonctions (cela se produit beaucoup lors de l'utilisation de frameworks comme JQuery).

Par conséquent, lorsque la recherche d'un identifiant échoue sur l'objet de la portée actuelle, il regarde l'objet de la portée suivante dans la chaîne. Il continue de marcher sur la chaîne jusqu'à ce qu'il touche l'objet global (les fonctions déclarées au niveau global ont l'objet global comme objet de portée).

Attribut Attribut Weirdness

Lorsque les navigateurs exécutent un code dans le texte d'un attribut tel que onclic, il traite ce code comme s'il s'agissait d'une fonction. Cependant, les navigateurs feront des choses étranges avec la chaîne de portée apparente attachée à cette «fonction». Typiquement, ils injectent l'élément actuel et l'élément du document (et peut-être d'autres éléments intermédiaires) comme s'ils étaient des objets de portée dans la chaîne de portée.

Par exemple, modifiez le code onclick dans votre exemple pour "alert (href)". Vous verrez le chemin de votre page suivi de # dans la zone d'alerte. C'est parce que l'élément actuel est dans la chaîne de portée et donc href est résolu par sa propriété href .

Dans le cas de la question, le code arrive au document dans la chaîne de portée (qui est placé au-dessus de l'objet de fenêtre global) et trouve l'identifiant "mytest" (qui fait référence à un formulaire) et donc tente d'utiliser la valeur de celui-ci En tant que fonction (et échoue).

La fonction est un membre dans l'objet de window , et le formulaire est un membre de la collection de forms dans l'objet de document . Lorsque le script cherche une correspondance pour l'identifiant "mytest", il regarde d'abord dans l'objet du document , et s'il n'est pas trouvé, il se trouve dans l'objet de la window .

Vous pouvez accéder à la fonction même avec le nom de formulaire en conflit si vous spécifiez qu'il se trouve dans l'objet de window :

 <a href="#" onClick="window.mytest();">Click Me</a>