web-dev-qa-db-fra.com

Comment fonctionne le Javascript en ligne (en HTML)?

Je sais que c'est une mauvaise pratique. N'écrivez pas un code comme celui-ci si possible.

Bien sûr, nous nous trouverons toujours dans des situations où un extrait intelligent de Javascript en ligne peut résoudre un problème rapidement.

Je poursuis cette question dans le but de bien comprendre ce qui se passe (et les pièges potentiels) lorsque quelque chose comme ceci est écrit:

<a href="#" onclick="alert('Hi')">Click Me</a>

Autant que je sache, c’est fonctionnellement la même chose que

<script type="text/javascript">
   $(function(){ // I use jQuery in this example
       document.getElementById('click_me').onclick = 
           function () { alert('Hi'); };
   });
</script>
<a href="#" id="click_me">Click Me</a>

En extrapolant, il semble que la chaîne affectée à l'attribut onclick soit insérée dans une fonction anonyme affectée au gestionnaire de clics de l'élément. Est-ce vraiment le cas?

Parce que je commence à faire des choses comme ça:

<a href="#" onclick="$(this).next().fadeIn(); return false;">Display my next sibling</a> <!-- Return false in handler so as not to scroll to top of page! --> 

Qui fonctionne Mais je ne sais pas à quel point c'est un bidouillage. Cela semble suspect car il n'y a aucune fonction apparente qui est retournée!

Vous pourriez demander, pourquoi faites-vous cela, Steve? Inline JS est une mauvaise pratique!

Pour être tout à fait honnête, je suis fatigué d’éditer trois sections de code différentes pour modifier une section de page, en particulier lorsque je prototype quelque chose pour voir s’il fonctionnera. C'est tellement plus facile et parfois même logique que le code spécifiquement lié à cet élément HTML soit défini à l'intérieur l'élément: Quand je décide 2 minutes plus tard que c'était une idée terrible, je peux nuke toute la div (ou autre chose) et je n'ai pas un tas de JS et CSS mystérieux qui traînent dans le reste de la page, ralentissant le rendu très légèrement. Ceci est similaire au concept de localité de référence, mais au lieu des erreurs de cache, nous examinons les bogues et le fiasco de code.

117
Steven Lu

La réponse est presque correcte, mais vous n'avez pas comptabilisé la valeur this fournie au code en ligne.

<a href="#" onclick="alert(this)">Click Me</a>

est en fait plus proche de:

<a href="#" id="click_me">Click Me</a>
<script type="text/javascript">
document.getElementById('click_me').addEventListener("click", function(event) {
    (function(event) {
        alert(this);
    }).call(document.getElementById('click_me'), event);
});
</script>

Les gestionnaires d'événements en ligne définissent this égal à la cible de l'événement. Vous pouvez également utiliser une fonction anonyme dans un script en ligne

<a href="#" onclick="(function(){alert(this);})()">Click Me</a>
87
apsillers

Que fait le navigateur quand vous avez

<a onclick="alert('Hi');" ... >

consiste à définir la valeur réelle de "onclick" sur quelque chose comme:

new Function("event", "alert('Hi');");

C'est-à-dire qu'il crée une fonction qui attend un paramètre "event". (Eh bien, IE ne le fait pas; cela ressemble plus à une simple fonction anonyme.)

8
Pointy

Il semble y avoir beaucoup de mauvaises pratiques sur les attributs du gestionnaire d'événements. Une mauvaise pratique est de ne pas savoir et d’utiliser les fonctionnalités disponibles là où cela est le plus approprié. Les attributs d'événement sont entièrement des normes documentées par le W3C et il n'y a aucune mauvaise pratique à leur sujet. Ce n'est pas différent que de placer des styles en ligne, ce qui est également documenté par le W3C et peut être utile à un moment donné. Que vous le placiez dans des balises de script ou non, cela sera interprété de la même manière.

https://www.w3.org/TR/html5/webappapis.html#event-handler-idl-attributes

6
Daniel B

La meilleure façon de répondre à votre question est de voir en action.

<a id="test" onclick="alert('test')"> test </a> ​

Dans le js

var test = document.getElementById('test');
console.log( test.onclick ); 

Comme vous le voyez dans la console, si vous utilisez chrome, il imprime une fonction anonyme avec l'objet événement transmis, bien que ce soit un peu différent dans IE.

function onclick(event) {
   alert('test')
}

Je suis d'accord avec certains de vos points concernant les gestionnaires d'événements en ligne. Oui, ils sont faciles à écrire, mais je ne partage pas votre idée de devoir changer de code à plusieurs endroits. Si vous structurez bien votre code, vous ne devriez pas avoir à le faire.

4
aziz punjani

Cela semble suspect car il n'y a aucune fonction apparente qui est retournée!

C'est une fonction anonyme qui a été attachée à l'événement click de l'objet.

pourquoi tu fais ça, Steve?

Pourquoi diable faites-vous ..... Ah, ça ne fait rien, comme vous l'avez dit, c'est vraiment une mauvaise pratique largement adoptée :)

3
mattytommo

Essayez ceci dans la console:

var div = document.createElement('div');

div.setAttribute('onclick', 'alert(event)');

div.onclick

Dans Chrome, cela montre ceci:

function onclick(event) {
  alert(event)
}

... et la propriété non standard name de div.onclick est "onclick".

Donc, que cela soit anonyme ou non dépend de votre définition du terme "anonyme". Comparez avec quelque chose comme var foo = new Function(), où foo.name est une chaîne vide et foo.toString() produira quelque chose comme

function anonymous() {

}
3
Dagg Nabbit