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 require
fonction est appelée, elle réinitialise l' this
objet à un objet vide et redéfinit module
pour 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 module
pour 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 module
qui s'y trouve exports
pour 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' this
objet est un objet vide, pourtant, la module
variable 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 module
dans la portée globale dans le navigateur, il sera placé dans l' this
objet, ce qui entraînera l'échec du test, car ce this.module
sera le même objet que le module. Sur le nœud, this.module
n'existe pas et module
existe 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 module
variable 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' module
inté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.