Hur fungerar inline Javascript (i HTML)?


Jag vet att detta är dålig praxis. Skriv inte kod på det här sättet om det alls är möjligt.

Självklart kommer vi alltid att hamna i situationer där en smart bit inline Javascript snabbt kan lösa ett problem.

Jag driver denna fråga i syfte att fullt ut förstå vad som händer (och de potentiella fallgroparna) när något sådant här skrivs:

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

Så vitt jag kan säga är detta funktionellt samma som

<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>

Om man extrapolerar från detta verkar det som att strängen som tilldelas attributet onclick sätts in i en anonym funktion som tilldelas elementets klickhanterare. Är detta verkligen fallet?

För att jag börjar göra saker som detta:

<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! --> 

Vilket fungerar. Men jag vet inte hur mycket av en hack detta är. Det ser misstänkt ut eftersom det inte finns någon uppenbar funktion som returneras från!

Du kanske frågar, varför gör du detta, Steve? Inbäddad JS är dålig praxis!

För att vara helt ärlig är jag trött på att redigera tre olika kodavsnitt bara för att ändra ett avsnitt på en sida, särskilt när jag bara prototypar något för att se om det överhuvudtaget kommer att fungera. Det är så mycket enklare och ibland till och med logiskt att koden som specifikt hör ihop med detta HTML-element definieras direkt i elementet: När jag två minuter senare beslutar att detta var en fruktansvärt, fruktansvärd idé kan jag ta bort hela div:en (eller vad det nu är) och jag har inte en massa mystisk JS- och CSS-skräp liggande kvar på resten av sidan, vilket sakta ner renderingen en aning. Detta liknar konceptet med locality of reference men istället för cache-missar tittar vi på buggar och kodöverbelastning.

Svar #1

Du har nästan fått det rätt, men du har inte tagit hänsyn till värdet på this som tillhandahålls till den inline-koden.

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

är faktiskt närmare:

<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>

Inline-händelsehanterare sätter this lika med målet för händelsen. Du kan också använda anonym funktion i inline-skript

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

Svar #2

Vad webbläsaren gör när du har

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

är att sätta det faktiska värdet av "onclick" till något som effektivt liknar:

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

Det vill säga, det skapar en funktion som förväntar sig en "händelse"-parameter. (Tja, IE gör det inte; det är mer som en vanlig enkel anonym funktion.)

Svar #3

Det verkar finnas mycket dålig praxis som sprids kring Event Handler-attribut. Dålig praxis är att inte känna till och använda tillgängliga funktioner där det är mest lämpligt. Eventattributen är fullt dokumenterade standarder av W3C och det finns inget dåligt med dem. Det är inget annorlunda än att placera inline-stilar, vilket också är W3C-dokumenterat och kan vara användbart ibland. Oavsett om du placerar det inneslutet i script-taggar eller inte, kommer det tolkas på samma sätt.

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

Relaterade artiklar