41 votes

Pourquoi le nom de la fonction JS est en conflit avec l'ID d'élément?

J'en ai deux presque identiques simple JS violons de l'appel d'une fonction sur sélectionnez modifier. Nom de la fonction est la même que select ID dans les deux cas, mais pour une raison quelconque, le premier violon fonctionne très bien, et la seconde échoue avec une erreur JavaScript is not a function:

http://jsfiddle.net/AZkfy/7/ - fonctionne très bien dans FF9 (Linux), Chrome 16 (Linux), IE8 (Windows):

<script>
    function border(border) {
      alert(border);
    }
</script>

<select id='border' name='border' onchange='border(this.value)'>
    <option value='foo'>foo</option>
    <option value='bar'>bar</option>
</select>

et

http://jsfiddle.net/cYVzk/ - échoue dans FF9 (Linux), Chrome 16 (Linux), IE8 (Windows):

<script>
    function border(border) {
      alert(border);
    }
</script>

<form>
<select id='border' name='border' onchange='border(this.value)'>
    <option value='foo'>foo</option>
    <option value='bar'>bar</option>
</select>
</form>

Premier de tous, je n'arrive pas à comprendre pourquoi le premier fonctionne bien, et le second échoue.

Deuxième - y a-JS les spécifications ou les restrictions en matière de conflit JS noms de fonction et de l'ID de l'élément?

64voto

PointedEars Points 4933

C'est un héritage de la portée de la chaîne d'émission provenant de JavaScript 1.0 à 1.3 quand il n'y a pas de distinction entre le langage de programmation et de ce que nous appelons aujourd'hui une API DOM ("Dynamic HTML" puis).

Si votre formulaire de contrôle (ici: un select élément) est partie d'un formulaire (descendant d'une form - éléments), puis l' Form objet qui représente l' form élément est la troisième suivante dans le champ d'application de la chaîne de code dans le contrôle du gestionnaire d'événements de valeurs d'attribut (deuxième-ensuite le formulaire de contrôle de l'objet lui-même, suivant est la Variable Objet de ce code).

JavaScript™ a été conçu par Brendan Eich (puis à Netscape) comme un langage de programmation facile à utiliser pour les débutants et qui fonctionne bien avec des documents HTML (comme un complément de Sun Java; d'où la jamais de confusion de nom). Parce que dans les premiers jours de la langue et de (Netscape) API DOM ont été, cette (sur)la simplification appliquée à l'API DOM ainsi: Un Form objet a les noms des contrôles contenus dans la forme qu'elle se représente comme les noms de ses propriétés qui font référence à la forme des objets de contrôle. OIE, vous pouvez écrire

myForm.border

qui est le propriétaire d'abréviation de l'conforme aux normes (W3C DOM Niveau 2 HTML), mais également rétro-compatible

document.forms["myForm"].elements["border"]

Maintenant, si vous utilisez un contrôle de formulaire dans un gestionnaire d'événements de la valeur de l'attribut d'un contrôle de formulaire dans un formulaire, comme

<form …>
  <… name="border" onchange='border(this.value)' …>
</form>

c'est le même que si vous aviez écrit la moitié de propriété

<form …>
  <… name="border" onchange='this.form.border(this.value)' …>
</form>

ou l'conforme aux normes

<form …>
  <… name="border" onchange='this.form.elements["border"](this.value)' …>
</form>

en raison d'un potentiel global border() fonction est une propriété de l' ECMAScript Objet Global qui est le dernier, après l' Form objet (un objet implémentant l' HTMLFormElement interface dans le DOM du W3C), dans le champ d'application de la chaîne.

Toutefois, le formulaire de contrôle de l'objet visé ici par border n'est pas appelable (ne pas mettre en œuvre l'ECMAScript interne [[Call]] méthode ou la met en œuvre, de sorte qu'il déclenche une exception quand on l'appelle). Donc, si vous essayez d'appeler l'objet avec l' border(this.value), un TypeError exception est levée, que vous devriez voir dans le script consoles (comme "TypeError: la frontière n'est pas une fonction" dans les Outils de développement de Chrome 16.0.912.77 [Développeur pour Construire 118311 Linux]).

Microsoft, Netscape concurrent dans les années 1990, avait pour copier cette fonctionnalité pour le MSHTML DOM sorte que le code écrit pour Netscape irait également dans Internet Explorer (3.0), avec JScript (1.0). Et les concurrents de Microsoft a copié à leur DOM implémentations pour exactement la même raison. Il est devenu une partie d'un quasi-standard (maintenant appelé "DOM Niveau 0").

Puis vint le DOM Niveau 2 Spécification HTML, un effort continu visant à normaliser et à étendre les caractéristiques communes des DOM existant implémentations à l'époque. Une Recommandation du W3C depuis 2003-01-09, son Langage ECMAScript de Liaison indique que les points de HTMLCollections peuvent être accessibles par leur nom ou ID avec le support de la propriété de l'accesseur de la syntaxe [...], équivalent à l'appel de l' namedItem() méthode de l'objet de la mise en œuvre de l' HTMLCollection interface.

form élément d'objets et d'objets éléments pour les contrôles de formulaire dans les formes sont des éléments de HTMLCollections dans le DOM du W3C, HTMLDocument::forms et HTMLFormElement::elements, respectivement. Mais pour la compatibilité ascendante dans les navigateurs,

document.forms["myForm"].elements["myControl"]

doit être équivalent à

document.myForm.myControl

Ainsi, avec la mise en œuvre du W3C DOM Niveau 2 interfaces HTML au plus tard, cette fonctionnalité a commencé à s'appliquer à des éléments avec l'ID (id valeur de l'attribut) ainsi (ce qui peut être vu dans le Chrome, par exemple).

En conséquence, la commodité fonctionnalité introduite dans le code JavaScript™ 16 ans toujours les morsures de vous comme d'un bug dans le côté client DOM scripting aujourd'hui.

Si vous évitez d'utiliser le même nom ou l'ID pour les contrôles de formulaire et les formes que vous utilisez comme identifiant de fonctions définies par l'utilisateur, et qui sont déjà utilisés pour les construit-dans les propriétés du formulaire (comme action, submit, et reset), alors cela devient de moins en moins un problème. Aussi, c'est une mauvaise idée d'utiliser le même identifiant pour la fonction et l'un de ses arguments (code source de confusion de côté) qui rend la fonction de l'objet inaccessible à partir de la fonction (la Variable Objet de la fonction de contexte, d'abord dans son champ d'application de la chaîne).

5voto

Christoph Points 23467

IE réserve automatiquement un var ID = domElement; dans l'espace global pour chaque élément DOM avec un ID . Certains autres navigateurs ont adopté ce comportement.

Essayez toujours d'éviter d'utiliser les mêmes identifiants et noms de version! Vous pouvez également utiliser votre propre espace de noms dans JS pour éviter les collisions.

MODIFIER:

Je ne sais pas pourquoi l'un de vos exemples échoue, alors que l'autre fonctionne. Il peut s’agir d’un simple ordre chronologique / d’ordre d’exécution causé par l’emballage <form> .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X