Le problème lorsque vous essayez de déterminer dans quel environnement votre code s'exécute est que tout objet peut être modifié et déclaré, ce qui rend presque impossible de déterminer quels objets sont natifs de l'environnement et lesquels ont été modifiés par le programme.
Cependant, il existe quelques astuces que nous pouvons utiliser pour déterminer avec certitude dans quel environnement vous vous trouvez.
Commençons par la solution généralement acceptée utilisée dans la bibliothèque de soulignement:
typeof module !== 'undefined' && module.exports
Cette technique est en fait parfaitement adaptée pour le côté serveur, car lorsque la requirefonction est appelée, elle réinitialise l' thisobjet à un objet vide et redéfinit modulepour vous à nouveau, ce qui signifie que vous n'avez pas à vous soucier de toute falsification extérieure. Tant que votre code est chargé avec require, vous êtes en sécurité.
Cependant, cela s'effondre sur le navigateur, car tout le monde peut facilement définir modulepour donner l'impression que c'est l'objet que vous recherchez. D'une part, cela peut être le comportement que vous souhaitez, mais cela détermine également les variables que l'utilisateur de la bibliothèque peut utiliser dans la portée globale. Peut-être que quelqu'un veut utiliser une variable avec le nom modulequi s'y trouve exportspour une autre utilisation. C'est peu probable, mais qui sommes-nous pour juger des variables que quelqu'un d'autre peut utiliser, simplement parce qu'un autre environnement utilise ce nom de variable?
L'astuce cependant, c'est que si nous supposons que votre script est en cours de chargement dans la portée globale (ce qu'il sera s'il est chargé via une balise de script), une variable ne peut pas être réservée dans une fermeture externe, car le navigateur ne le permet pas . Souvenez-vous maintenant que dans node, l' thisobjet est un objet vide, pourtant, la modulevariable est toujours disponible. C'est parce qu'il est déclaré dans une fermeture externe. Nous pouvons donc corriger la vérification du soulignement en ajoutant une vérification supplémentaire:
this.module !== module
Avec cela, si quelqu'un déclare moduledans la portée globale dans le navigateur, il sera placé dans l' thisobjet, ce qui entraînera l'échec du test, car ce this.modulesera le même objet que le module. Sur le nœud, this.modulen'existe pas et moduleexiste dans une fermeture externe, donc le test réussira, car ils ne sont pas équivalents.
Ainsi, le test final est:
typeof module !== 'undefined' && this.module !== module
Remarque: Bien que cela permette maintenant à la modulevariable d'être utilisée librement dans la portée globale, il est toujours possible de contourner cela sur le navigateur en créant une nouvelle fermeture et en déclarant à l' moduleintérieur, puis en chargeant le script dans cette fermeture. À ce stade, l'utilisateur réplique entièrement l'environnement de nœud et, espérons-le, sait ce qu'il fait et essaie de faire un style de nœud requis. Si le code est appelé dans une balise de script, il sera toujours à l'abri de toute nouvelle fermeture externe.