web-dev-qa-db-fra.com

Comment l'emplacement d'une balise de script dans une page affecte-t-il une fonction JavaScript qui y est définie?

J'ai lu que vous devez définir vos fonctions JavaScript dans le <head> tag, mais comment l'emplacement du <script> (que ce soit dans le <head>, <body>, ou toute autre balise) affecte une fonction JavaScript.

Plus précisément, comment cela affecte-t-il la portée de la fonction et d'où vous pouvez l'appeler?

43
Mark Rogers

Demander aux gens d'ajouter <SCRIPT> seulement dans la tête sonne comme une chose raisonnable à faire, mais comme d'autres l'ont dit, il y a plusieurs raisons pour lesquelles ce n'est pas recommandé ou même pratique - principalement la vitesse et la façon dont les pages HTML sont générées dynamiquement.

C'est ce que le spécification HTML 4 dit :

L'élément SCRIPT place un script dans un document. Cet élément peut apparaître un certain nombre de fois dans le HEAD ou BODY d'un document HTML.

Et quelques exemples de HTML. N'est-ce pas joli tout formaté ici :)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
     "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<HEAD>
<TITLE>A document with SCRIPT</TITLE>
<META http-equiv="Content-Script-Type" content="text/tcl">
<SCRIPT type="text/vbscript" src="http://someplace.com/progs/vbcalc">
</SCRIPT>
</HEAD>
<BODY>
<SCRIPT type="text/javascript">
...some JavaScript...
</SCRIPT>
</BODY>
</HTML>

Et quelque chose à attendre dans HTML 5 :

Nouvel attribut asynchrone dans <SCRIPT>:

Remarque: Il existe plusieurs façons [sic] d'exécuter un script:

L'attribut async est "true": le script sera exécuté de manière asynchrone avec le reste de la page, donc le script sera exécuté pendant que la page continue l'analyse.

L'attribut async est "false", mais l'attribut defer est "true": le script sera exécuté lorsque la page sera terminée avec l'analyse.

26
Simon_Weaver

Les règles de jeu normales sont toujours d'actualité; n'utilisez pas des choses avant qu'elles ne soient définies. :)

Notez également que le conseil de "tout mettre en bas" n'est pas la seule règle du livre - dans certains cas, il peut ne pas être possible et dans d'autres cas, il peut être plus judicieux de mettre le script ailleurs.

La raison principale pour laquelle un script est placé en bas d'un document est la performance, les scripts, contrairement aux autres requêtes HTTP, ne se chargent pas en parallèle, ce qui signifie qu'ils ralentiront le chargement du reste de votre page. Une autre raison pour mettre les scripts en bas est que vous n'avez pas besoin d'utiliser de fonctions "DOM ready". Puisque la balise de script est en dessous de tous les éléments, le DOM sera prêt à être manipulé!

EDIT: Lisez ceci: http://developer.yahoo.com/performance/rules.html#js_bottom

19
James

L'un des aspects du placement est la performance. Voir ce bel article dans la discussion YSlow pour pourquoi il est parfois recommandé de les mettre en bas du document.

En ce qui concerne les questions de portée, les règles de visibilité habituelles pour Javascript (variables définies à l'intérieur ou à l'extérieur des fonctions, locales, globales, fermetures, etc.) ne sont pas affectées à ma connaissance.

9
Alan

La position de la balise de script est importante. Si vous liez une fonction avec un élément de document, l'élément de document doit d'abord être chargé avant d'implémenter la fonction. supposons que getTeachers () est une fonction du fichier getTeachers.js. Cela vous donnera une erreur:

<html xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Unit Teachers</title>
<head>
 <script type="text/javascript" src="getTeachers.js"></script>
 <script type="text/javascript">
document.getElementById("buttonId").onclick=function(){getResults()};

</script>
 </head>
 <body>
 <form>
 <input type = "button" id="buttonId" value = "Press for Results"  /><br />
 </form>

<span id="results" /></span>
</body>
</html>

Il donne une erreur avant que la tête ne soit chargée en premier et il ne peut pas trouver d'élément avec l'ID spécifié. Le code ci-dessous est une correction:

<html xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Unit Teachers</title>
<head>
 <script type="text/javascript" src="getTeachers.js"></script>

 </head>
 <body>
 <form>
 <input type = "button" id="buttonId" value = "Press for Results"  /><br />
 </form>
<script type="text/javascript">
document.getElementById("buttonId").onclick=function(){getResults()};

</script>
<span id="results" /></span>
</body>
</html>
4
Dhwaneel

Ce n'est pas le cas. La plupart des scripts de dispersion du framework de programmation tout au long de la page. Je n'ai que rarement rencontré des problèmes à cause de cela (et uniquement à partir de navigateurs plus anciens).

2
TheSmurf

Si vous extrayez des Javascripts via XMLHttpRequest, comme l'a dit Diodeus, cela ne fonctionnera probablement pas. Dans mon cas, il n'y a pas eu d'erreur, le navigateur ignore simplement les nouveaux scripts.

J'ai fini par utiliser cela, pas terriblement élégant mais qui fonctionne pour moi jusqu'à présent:

http://zeta-puppis.com/2006/03/07/javascript-script-execution-in-innerhtml-the-revenge/

Comment utiliser execJS: http://zeta-puppis.com/2006/02/23/javascript-script-execution-in-innerhtml/

Remarque: faites attention à &lt; Sur cette ligne: for(var i=0;i<st.length; i++)

2
PJ Brunet

Si votre script fait référence à un ID sur la page et que la page n'a pas été rendue (c'est-à-dire que le script est avant HTML ou que votre script est exécuté avec onload, plutôt que le DOM est prêt), vous pouvez également obtenir une erreur.

Si vous avez un script en ligne (fonctions externes) situé avant les fonctions qu'il peut appeler, vous pouvez obtenir une erreur car elles ne sont peut-être pas encore disponibles. Je ne dis pas que cela va toujours se produire, mais cela peut dépendre du type ou de la version du navigateur.

1
Otávio Décio

Les règles de portée de Javascript sont similaires à Perl - vous pouvez appeler n'importe quelle fonction au niveau actuel ou supérieur. La seule restriction est que la fonction doit être définie au moment où vous l'appelez. La position dans la source n'est pas pertinente - seule la position dans le temps compte.

Vous devez éviter de placer des scripts dans le <head> si possible car cela ralentit l'affichage de la page (voir le lien publié par Alan).

1
user42092