Importere andre JS-filer i JavaScript
Skrevet av Arild den 17. June, 2011 i Programmering, Webutvikling |
0 kommentarer
Mange programmeringsspråk har måter for å importere filer i koden, for eksempel klasser, interfaces, selvstendige skript, o.l. I Java brukes import, mens i C# bruker vi nøkkelordet using. Men hvordan gjør vi dette i JavaScript? Det er dessverre ikke like enkelt. Men det er heldigvis et lite triks som gjør det hele mulig.
Inkludere JavaScript-fil i HTML
For å illustrere dette ser vi først på hvordan man inkluderer et JavaScript i et HTML-dokument. Her er et eksempel:
<!doctype html> <html lang="no"> <head> <meta charset="utf-8"> <title>Mitt HTML-dokument</title> </head> <body> <!-- Innhold i HTML-dokumentet ... --> <script type="text/javascript" src="inkluderMeg.js"></script> </body> </html>
Mesteparten av koden er uvesentlig i denne sammenhengen. Vi fokuserer kun på linje 9 og 10. Her inkluderes JavaScript-filen inkluderMeg.js ved hjelp av script-tagen. Selve filnavnet oppgis i src-attributtet. Dersom du ønsker å inkludere flere JS-filer, må du legge til en ny script-tag for hver fil.
Inkludere JavaScript-fil i JavaScript
Det er nettopp dette vi drar nytte av for å løse problemet vårt. Løsningen går ut på å lage en funksjon i JavaScript som legger til en script-tag inn i body-tagen vår, etter resten av innholdet. Dette gjør vi ved å manipulere dokumentobjekt-modellen (DOM-en) som nettleseren vår oppretter basert på HTML-koden vi har skrevet. Under følger JavaScript-koden som trengs for å oppnå vår ønskede importeringsfunksjon:
function import(scriptFileName) {
var body = document.getElementsByTagName("body")[0];
var script = document.createElement("script");
script.setAttribute("script", "text/javascript");
script.setAttribute("language", "javascript");
script.setAttribute("src", scriptFileName + ".js");
body.appendChild(script);
}
1) Funksjonen vår tar imot ett parameter, scriptFileName, som er navnet på scriptet vårt – uten «.js»-endelsen. 3) Vi finner body-tagen i DOM-en. 5) Vi oppretter en ny tag av typen script. 7-9) Vi setter attributter som opplyser om hvilket skriptspråk og hvilken fil vi skal inkludere. 11) Vi legger til script-tagen til body-tagen i DOM-en.
For å inkludere inkluderMeg.js med denne funksjonen er det altså nok å skrive:
import("inkluderMeg");
Du kan teste dette ved å opprette tre filer: index.html, mittScript.js og inkluderMeg.js (du finner de ferdige filene nederst i blogginnlegget). Filene ligger i samme mappe og har følgende forhold til hverandre (piler representerer inkludering):
Skriv følgende i de respektive filene (markert med en kommentar):
<!-- index.html --> <!doctype html> <html lang="no"> <head> <meta charset="utf-8"> <title>Mitt HTML-dokument</title> </head> <body> <!-- Innhold i HTML-dokumentet ... --> <script type="text/javascript" src="mittScript.js"></script> </body> </html>
// mittScript.js
import("inkluderMeg");
function import(scriptFileName) {
var body = document.getElementsByTagName("body")[0];
var script = document.createElement("script");
script.setAttribute("script", "text/javascript");
script.setAttribute("language", "javascript");
script.setAttribute("src", scriptFileName + ".js");
body.appendChild(script);
}
// inkluderMeg.js var tekst = "Hei hei!"; alert(tekst);
index.html er altså et helt «tomt» HTML-dokument som importerer mittScript.js. Denne JavaScript-filen inneholder funksjonen import(scriptFileName). Den kaller i tillegg på denne funksjonen og oppgir «inkluderMeg» som parameter. Dette kallet gjør at inkluderMeg.js importeres inn i HTML-dokumentet. For å sjekke om filen har blitt importert, har vi lagt inn et alert-kall. Hvis alt er gjort riktig, skal du nå få følgende pop-up når du åpner index.html i nettleseren din.
Innlasting tar tid
Dessverre er det ikke slik at et skript i DOM-en blir prosessert, og så kjøres neste linje i fila som importerte skriptet. Det tar rett og slett litt tid å prosessere innholdet. Dette kan vi bevise ved å endre på innholdet til mittScript.js og inkluderMeg.js, slik at førstnevnte prøver å bruke variabelen tekst som er initiert i sistnevnte:
// mittScript.js
import("inkluderMeg");
alert(tekst);
function import(scriptFileName) {
var body = document.getElementsByTagName("body")[0];
var script = document.createElement("script");
script.setAttribute("script", "text/javascript");
script.setAttribute("language", "javascript");
script.setAttribute("src", scriptFileName + ".js");
body.appendChild(script);
}
// inkluderMeg.js var tekst = "Hei hei!";
Hvis du nå laster index.html på nytt, vil det tilsynelatende skje ingenting. Åpner du derimot Console-fanen inne på Web Inspector (Ctrl + Shift + i i Chrome), står det følgende feilmelding:
Tilbakekall
Problemet er altså at vi prøver å aksessere en variabel i et skript som ennå ikke er kjørt. Hvordan løser vi dette? Jo, vi gjør det mulig for brukeren som skal importere en skriptfil, å angi et tilbakekall (eng. callback). Et tilbakekall er en helt ordinær funksjon som blir påkalt så fort en viss hendelse har inntruffet. I vårt tilfelle er hendelsen at skriptet vårt er ferdig prosessert. I koden nedenfor er tilbakekallsfunksjonen vår onImported(), og den skal bli påkalt når skriptet som importeres, er ferdig prosessert:
function onImported() {
alert(tekst);
}
import("inkluderMeg", onImported);
function import(scriptFileName, callback) {
var body = document.getElementsByTagName("body")[0];
var script = document.createElement("script");
script.setAttribute("script", "text/javascript");
script.setAttribute("language", "javascript");
script.setAttribute("src", scriptFileName + ".js");
body.appendChild(script);
script.onload = callback;
}
De viktigste linjene er 1-3, 5, 7 og 19. På linje 1-3 har vi definert funksjonen som skal bli påkalt når skriptet er innlastet og prosessert. På linje 7 er vår oppgraderte import-funksjon deklarert. Den inneholder nå et nytt parameter, callback, som refererer til funksjonen som skal påkalles når skriptet er prosessert. Dette angir vi på linje 19 ved hjelp av onload-attributtet. På linje 5 kaller vi på den nye import-funksjonen vår og angir onImported som vår tilbakekallsfunksjon.
Merk at parenteser ikke skal være med bak funksjonsnavnet når vi agnir funksjonen som referanse. Hvis vi setter på et par parenteser etter funksjonsnavnet her, vil det føre til at funksjonen blir påkalt prematurt.
Hvorfor?
Så, hvorfor skulle du ønske å gå gjennom alt dette bryet for å importere JavaScript-filer? Du kunne jo like gjerne bare angitt alle JavaScript-filene manuelt i script-tager i HTML-dokumentet, ikke sant?
Vel, det er et par fordeler ved å gjøre det på denne måten:
- Du kan gjøre betinget importering. La oss si at du har et JavaScript som kun trengs når nettsiden din åpnes på en mobil. Det er direkte sløsing av ressurser å importere dette skriptet når gjesten din besøker nettsiden din fra sin desktop-nettleser. Du kan bruke JavaScript til å sjekke hvilken nettleser gjesten din bruker, og importere de nødvendige JavaScript-filene deretter.
- Hvis du har et større JavaScript, er det alltid lurt å dele komponentene utover flere filer. La heller din primære JavaScript-fil (der hvor skriptet startes) foreta importeringen istedenfor HTML-en. På denne måten blir JavaScriptet ditt mindre avhengig av HTML-koden din.





Kommentarer