Um novo padrão para o objeto global no JavaScript
O objeto global no JavaScript é, no mínimo, peculiar. Muitos novatos na linguagem acabam cometendo erros graves por não saberem exatamente como o objeto global funciona. Até mesmo programadores experientes em outras linguagens podem enfrentar dificuldades em entender e utilizar o objeto global.
Vejamos o exemplo abaixo:
function calc(x, y) { a = x + y; b = 3; c = a + b; return c; }
Este código funciona perfeitamente e, ao chamar a função calc(1,2)
, o resultado será o esperado 6
. O JavaScript permite que variáveis sejam criadas sem a utilização das keywords var
, let
ou const
. Porém, ao omiti-las, estamos colocando estas variáveis no objeto global. No caso do navegador, ao executar a função calc
estamos criando as variáveis a
, b
e c
no objeto global window
. window.a // 3 window.b // 3 window.c // 6
Por este e por outros motivos, é sempre recomendado utilizar o strict mode, que basicamente define uma semântica mais restrita ao JavaScript. function calc(x, y) { "use strict"; a = x + y; b = 3; c = a + b; return c; }
Ao chamar a função calc
com a definição use strict
no seu corpo, teremos o seguinte erro: Uncaught ReferenceError: a is not defined
. Isto porque o strict mode não permite que variáveis sejam definidas sem o uso de var
, let
ou const
. No ambiente do Node.js o problema é o mesmo, com a diferença de que o objeto global não é o window
, mas sim o global
. Objeto global no Node.js É mais complicado do que isso O objeto global ainda pode ser acessado de outras formas, dependendo do contexto. this O this
, no escopo global do navegador, irá sempre referenciar ao objeto window
. Já no ambiente Node.js, isso não irá funcionar, pois módulos no Node.js possuem o seu próprio escopo. E ainda existem mais diferenças relacionadas ao this
e à maneira de chamar funções. O artigo do Dr. Axel Rauschmayer sobre global
mostra ainda mais exemplos. O Felipe Moura também tem um artigo bem completo sobre o this. self A variável global self
funciona em iframes
, janelas, Web Workers, Service Workers, porém, não funciona no ambiente Node.js. Estão me acompanhando aqui? Já deu pra notar que não existe uma maneira padrão para acessar o objeto global independentemente do ambiente, certo? Obviamente, a comunidade criou soluções alternativas, como o exemplo abaixo: (typeof window !== "undefined" ? window : (typeof process === 'object' && typeof require === 'function' && typeof global === 'object') ? global : this);
A verdade é que até hoje não temos um standard para acesso ao objeto global, mas isso está prestes a mudar. A proposta Jordan Harband é o autor da proposta que irá introduzir ao objeto global a variável global
. A especificação já está no estágio 3 do processo do TC-39 e, ao que tudo indica, já poderemos utilizar o global
na ES2017. O autor da especificação criou um polyfill para que seja possível já utilizar e testar o global
hoje. // Computing the value of `global` import getGlobal from 'system.global'; const global = getGlobal(); // Shimming `global` (“installing” it) import shim from ‘system.global/shim’; shim();
Conclusão A ES2015 e ES2016 trouxeram uma série de correções e melhorias para o JavaScript, mas a linguagem continua constantemente evoluindo. Existem atualmente uma série de propostas que, assim como o global
, estão em estágio 3. O global
facilitará o entendimento de como o objeto global funciona e principalmente possibilitará a interoperabilidade em navegadores e no Node.js. Vale lembrar que o processo de evolução da especificação do JavaScript passa por 4 fases, tendo como objetivo validar propostas, expor para a comunidade e garantir através de pesquisas e testes que a funcionalidade/melhoria não irá quebrar a Web. Isso ocorreu com o global
e está explícito na documentação: Further research has determined that using global will not break existing code Traduzindo, "Uma pesquisa adicional determinou que o uso do global
não irá quebrar códigos existentes". Referências ES proposal: global proposal-global TC-39 proposal global