11572 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous

Dans un fichier xx.js je définis une variable CHANGEEDIT
Dans un fichier yy.js je veux savoir si le fichier xx.js est disponible

Dans le passé, si je voulais tester si une variable n'était pas définie j'écrivais

if(typeof CHANGEEDIT=== 'undefined')


Je constate que si cela fonctionne toujours sous Firefox ce n'est plus le cas sous Chrome
Je reçois le message d'erreur
Uncaught ReferenceError: CHANGEEDIT is not defined

J'ai trouvé un contournement qui ne me satisfait guère
En tête de yy.js j'écris
try {
	var EDITFLAG = CHANGEEDIT;
}
catch(error) {
	var EDITFLAG = false;
}

et dans le corps de ce fichier je teste if(EDITFLAG) chaque fois que je veux savoir si je peux ou non accéder à une fonction définie dans xx.js

Existe-t-il une solution moins lourde à ce problème ?
Merci de votre aide.
Modifié par PapyJP (19 Feb 2026 - 19:46)
Modérateur
Bonjour,

Voici un test avec

var, let, const et Class testés avec typeOf et window.hasOwnProperty() pour voir ce que l'on trouve selon q'une variable est déclarée, définie ou pas.

Bizarrement , dans le codepen typeOf ne lève pas d'erreurs dans chrome : Version 145.0.7632.76 (Build officiel) (64 bits) mais bon, c'est un codepen.

https://codepen.io/gc-nomade/pen/GgqaKRN?editors=1011

Cdt
Modifié par gcyrillus (16 Feb 2026 - 11:42)
Bonsoir Papy,

Durant des années j'ai utilisé la même approche que toi, notamment pour appeler les variables de bibliothèques sur lesquelles je n'avais pas la main :
/**
 * Test la présence de la bibliothèque Leaflet.js chargée en asynchrone et, si oui, exécution du script de configuration.
 * @param {object} L est une variable globale produite par Leaflet, elle nous permettra de tester l'initialisation de la bibliothèque.
 * @note typeof permet de tester la variable sans que celle-ci produise une erreur si elle n'est pas définie.
 */
window.addEventListener('load', () => {
  if (typeof L !== 'undefined') maps()

  document.addEventListener('readystatechange', () => {
    if (document.readyState === 'complete' && typeof L !== 'undefined') maps()
  })
})

Mais par la suite, depuis deux ou trois ans, j'utilise quelque chose de beaucoup plus fiable, à savoir : les mutations observers. Désormais je fais quelque chose comme ceci :
function initializeMaps(callback) {
  if (window.L) {
    callback()
    return true
  }
  return false
}

if (!initializeMaps(maps)) {
  const observer = new MutationObserver(() => {
    if (initializeMaps(maps)) {
      observer.disconnect()
    }
  })

  // Observer uniquement le head
  observer.observe(document.head, { childList: true, subtree: true })

  // Arrêter l'observation après 10 secondes
  setTimeout(() => observer.disconnect(), 10000)
}

Malheureusement je n'ai pas documenté le pourquoi de mon passage de la première à la deuxième solution, je ne me souviens plus ce que cela résout exactement. J'ai d'autant plus de mal à me rappeler que j'ai arrêté de faire du web depuis quelques temps maintenant (j'y reviendrais peut-être, mais pas dans l’immédiat)...
Modifié par Olivier C (18 Feb 2026 - 20:46)
Merci pour cette réponse.
Si je comprends bien il s'agit de se synchroniser sur le chargement d'une librairie externe.
Dans mon cas, il s'agit de détecter si on est en mode "administrateur", auquel cas les fonctions s'appliquent, ou en mode utilisateur. Il me suffit de tester autrement dans quel mode je me trouve.
Ce que je trouve bizarre, c'est que typeof CHANGEEDIT=== 'undefined' envoie un message d'erreur. S'il faut qu'une variable soir définie pour qu'on puisse tester si elle est définie ....
Bonsoir,

a écrit :
Ce que je trouve bizarre, c'est que typeof CHANGEEDIT=== 'undefined' envoie un message d'erreur. S'il faut qu'une variable soir définie pour qu'on puisse tester si elle est définie ....



Ce n'est pas bizarre. C'est le signe que JavaScript devient de plus en plus strict, moins permissif avec les années, et c'est généralement très bien à mon avis.

A tout hasard, as-tu essayé typeof(CHANGEEDIT)=='undefined' ? Juste pour s'assurer que ce n'est pas une bête erreur de priorité des opérateurs. i.e. typeof(CHANGEEDIT=='undefined'), ce qui expliquerait un peu plus clairement pourquoi ça provoque une erreur.

Si tu testes une variable globale, window.CHANGEEDIT devrait faire l'affaire, ou sinon une déclaration sans assignation en début de fichier i.e. var CHANGEEDIT; qui ne va rien faire si la variable existe déjà (attention à utiliser var, pas let, même en ES6+).
Tester la définition d'une variable locale n'a normalement pas de sens.
Modérateur
PapyJP a écrit :
Smiley confus
ça laisse penser....


en fait il y a une info que tu ne donnais pas:
Comment tu déclares cette variable si présente: var, let, const ou Class ?

Pour infos:
L'attribut "defer" sur les balise script (tes deux fichiers) permet de conserver l'ordre de chargement des script sans bloquer le chargement de la page.

Mon humble avis:
Personnellement, je teste coté serveur si le visiteur est connecté et que cette utilisateur existe ($_SESSION) avec les droits adéquats avant d'envoyer la page.

Cdt
gcyrillus a écrit :
en fait il y a une info que tu ne donnais pas:
Comment tu déclares cette variable si présente: var, let, const ou Class ?

j'ai pour habitude de définir les globales par var avec le nom en majuscules.
gcyrillus a écrit :
Personnellement, je teste coté serveur si le visiteur est connecté et que cette utilisateur existe ($_SESSION) avec les droits adéquats avant d'envoyer la page.

Ce que je fais côté serveur c'est de ne charger la partie sensible en js que si l'utilisateur a les droits d'administrateur.
Le résultat c'est que les fonctions d'administration n'existent pas pour les utilisateurs lambda, d'où la nécessité de tester la présence de ces fonctions dans le code commun.
Par exemple si on clique sur certains textes, il ne se passe rien si c'est un utilisateur lambda et ça ouvre une boîte de contrôle si c'est un administrateur.
Bien entendu je peux tester ça autrement, et c'est ce que vais faire.

Mon problème c'est toujours "pourquoi typeof variable === 'undefined' lève une erreur si la variable n'est pas définie ? J'ai utilisé cette technique sans problèmes pendant des décennies...

En ce qui concerne "defer" je vais regarder les conséquences sur le code.
En général je mets un appel à un script à la fin du code HTML. Puis-je être sûr que le script sera chargé à ce moment là si j'utilise defer ?
Modifié par PapyJP (20 Feb 2026 - 12:35)
Modérateur
PapyJP a écrit :

En ce qui concerne "defer" je vais regarder les conséquences sur le code.
En général je mets un appel à un script à la fin du code HTML. Puis-je être sûr que le script sera chargé à ce moment là si j'utilise defer ?


teste l'attribut defer sur l'appel aux deux scripts que tu as, ils devraient se charger l'un après l'autre.

Pour ta methode , typeof variable === 'undefined' mon Chrome ne me lève aucune erreur . Une solution est probablement de définir une valeur par défaut si non connecté ou mieux de servir une version différente de yy.js selon, sans xx.js

cdt
Modifié par gcyrillus (20 Feb 2026 - 16:01)
J'ai modifié mon code, je teste sur autre chose, cette erreur bizarre ne me gêne plus.

En ce qui concerne defer je suis dans la situation suivante

<html>
  <head>
    ....
	<script src="xx.js"></script>
	<script src="yy.js"></script>
	....
  </head>
  <body>
	....
	....
	....
	<script>makePage();</script>
  </body>
</html>

la fonction makePage est définie dans xx.js
Si je mets defer sur le chargement des fichiers .js, est-ce que je suis sûr que makePage() sera bien chargé avant d'être appelé en bas de la page ? D'après ce que j'ai lu sur le sujet, ça ne semble pas être le cas.
Smiley decu
Modifié par PapyJP (20 Feb 2026 - 17:36)
Modérateur
PapyJP a écrit :
J'ai modifié mon code, je teste sur autre chose, cette erreur bizarre ne me gêne plus.

En ce qui concerne defer je suis dans la situation suivante

<html>
  <head>
    ....
	<script src="xx.js"></script>
	<script src="yy.js"></script>
	....
  </head>
  <body>
	....
	....
	....
	<script>makePage();</script>
  </body>
</html>


la fonction makePage est définie dans xx.js
Si je mets defer sur le chargement des fichiers .js, est-ce que je suis sûr que makePage() sera bien chargé avant d'être appelé en bas de la page ? D'après ce que j'ai lu sur le sujet, ça ne semble pas être le cas.
Smiley decu


Idem, à ce que j'en comprend , defer n'a d’intérêt qu'en amont.
A voir si le navigateur prendrait en compte makePage() (depuis un fichier aussi externe) lorsque xx et yy ont l'attribut bien qu'il soit en aval du DOM ?
Cela ne me parait pas un problème sauf si xx et yy sont de gros fichier long à charger.

En faisant :

<script>
  document.addEventListener('DOMContentLoaded', () =>makePage(); 
</script>

Cela devrait suffire à lancer la fonction une fois les script en defer chargés

Cordialement
Modifié par gcyrillus (20 Feb 2026 - 18:54)
Merci de cette intéressante solution
Mes fichiers sont de petite taille mais il y en a plusieurs à charger. Ça peut être interessant de mettre defer et de synchroniser avec le listener.
Smiley smile
Modifié par PapyJP (23 Feb 2026 - 09:36)
Modérateur
Salut,

Je n'ai pas suivi toute la conversation. J'ai lu en Z.

PapyJP a écrit :

Dans un fichier xx.js je définis une variable CHANGEEDIT
Dans un fichier yy.js je veux savoir si le fichier xx.js est disponible


Pourquoi n'exportes tu pas la variable ?

xx.js

export const CHANGEEDIT = "quelque chose"


yy.js

import { CHANGEEDIT } from './chemin/vers/xx.js'
console.log(CHANGEEDIT)


html

    <script type="module" src="xx.js"></script>
    <script type="module" src="yy.js"></script>
Ma question était
Comment se fait-il qu’en fonction que j’utilise depuis des décennies (typeof XXX === 'undefined') provoque-t-elle une erreur sous Chrome?
Ce n’est pas de trouver un contournement au problème, j’ai déjà traité cette question en testant autre chose.
Modérateur
PapyJP a écrit :
Ma question était
Comment se fait-il qu’en fonction que j’utilise depuis des décennies (typeof XXX === 'undefined') provoque-t-elle une erreur sous Chrome?
Ce n’est pas de trouver un contournement au problème, j’ai déjà traité cette question en testant autre chose.


Es tu sûr que ce n'était pas une erreur de syntaxe ?
C’est peu probable, parce que ça marchait très bien avec Firefox.
En ce qui concerne mon programme j’ai changé le code et je ne peux plus faire de test. Quand j’aurai un peu de temps je ferai un petit programme de test pour en avoir le cœur net.
J'ai refait les tests, ça fonctionne correctement sous Firefox et Chrome.
Sans dont une erreur dans le code de la première version.