O problema de tentar descobrir em que ambiente seu código está executando é que qualquer objeto pode ser modificado e declarado, tornando quase impossível descobrir quais objetos são nativos do ambiente e quais foram modificados pelo programa.
No entanto, existem alguns truques que podemos usar para descobrir com certeza em que ambiente você está.
Vamos começar com a solução geralmente aceita usada na biblioteca de sublinhados:
typeof module !== 'undefined' && module.exports
Essa técnica é realmente perfeita para o servidor, pois quando a requirefunção é chamada, ela redefine o thisobjeto para um objeto vazio e redefine modulepara você novamente, o que significa que você não precisa se preocupar com adulterações externas. Enquanto seu código estiver carregado require, você estará seguro.
No entanto, isso desmorona no navegador, pois qualquer um pode definir facilmente modulepara fazer parecer que é o objeto que você está procurando. Por um lado, esse pode ser o comportamento que você deseja, mas também determina quais variáveis o usuário da biblioteca pode usar no escopo global. Talvez alguém queira usar uma variável com o nome moduleque possuiexports dentro dele para outro uso. É improvável, mas quem somos nós para julgar quais variáveis alguém pode usar, apenas porque outro ambiente usa esse nome de variável?
O truque, no entanto, é que, se estivermos assumindo que seu script está sendo carregado no escopo global (o que acontecerá se for carregado por meio de uma tag de script), uma variável não poderá ser reservada em um fechamento externo, porque o navegador não permite que . Agora lembre-se, no nó, o thisobjeto é um objeto vazio, mas a modulevariável ainda está disponível. Isso é porque é declarado em um fechamento externo. Assim, podemos corrigir a verificação do sublinhado adicionando uma verificação extra:
this.module !== module
Com isso, se alguém declarar moduleno escopo global no navegador, ele será colocado no thisobjeto, o que fará com que o teste falhe, porque this.moduleserá o mesmo objeto que o módulo. No nó, this.modulenão existe e moduleexiste dentro de um fechamento externo; portanto, o teste será bem-sucedido, pois não são equivalentes.
Assim, o teste final é:
typeof module !== 'undefined' && this.module !== module
Nota: Embora agora isso permita que a modulevariável seja usada livremente no escopo global, ainda é possível ignorá-la no navegador, criando um novo fechamento e declarando moduledentro disso, carregando o script nesse encerramento. Nesse ponto, o usuário está replicando completamente o ambiente do nó e, esperançosamente, sabe o que está fazendo e está tentando fazer um estilo de nó exigir. Se o código for chamado em uma tag de script, ele ainda estará protegido contra novos fechamentos externos.