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 require
função é chamada, ela redefine o this
objeto para um objeto vazio e redefine module
para 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 module
para 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 module
que 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 this
objeto é um objeto vazio, mas a module
variá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 module
no escopo global no navegador, ele será colocado no this
objeto, o que fará com que o teste falhe, porque this.module
será o mesmo objeto que o módulo. No nó, this.module
não existe e module
existe 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 module
variável seja usada livremente no escopo global, ainda é possível ignorá-la no navegador, criando um novo fechamento e declarando module
dentro 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.