Skip to content

Global object #123

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 16, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 61 additions & 129 deletions 1-js/06-advanced-functions/05-global-object/article.md
Original file line number Diff line number Diff line change
@@ -1,155 +1,87 @@

# Global object
# Objeto global

The global object provides variables and functions that are available anywhere. Mostly, the ones that are built into the language or the host environment.
O objeto global fornece variáveis e funções que estão disponíveis em qualquer lugar. Em sua maioria, aqueles que são incorporados ao idioma ou ao ambiente.

In a browser it is named "window", for Node.js it is "global", for other environments it may have another name.
No navegador ele é chamado de `window`, no Node.js é `global`, em outros ambientes pode ter outro nome.

For instance, we can call `alert` as a method of `window`:
Recentemente, `globalThis` foi adicionado a linguagem como um nome padrão para o objeto global, que deve ser suportado em todos os ambientes. Em alguns navegadores, como o "non-Chromium Edge", `globalThis` ainda não é suportado, mas pode ser facilmente utilizado através de um polyfill.

```js run
alert("Hello");

// the same as
window.alert("Hello");
```

We can reference other built-in functions like `Array` as `window.Array` and create our own properties on it.

## Browser: the "window" object

For historical reasons, in-browser `window` object is a bit messed up.

1. It provides the "browser window" functionality, besides playing the role of a global object.

We can use `window` to access properties and methods, specific to the browser window:

```js run
alert(window.innerHeight); // shows the browser window height

window.open('http://google.com'); // opens a new browser window
```

2. Top-level `var` variables and function declarations automatically become properties of `window`.

For instance:
```js untrusted run no-strict refresh
var x = 5;

alert(window.x); // 5 (var x becomes a property of window)

window.x = 0;

alert(x); // 0, variable modified
```

Please note, that doesn't happen with more modern `let/const` declarations:

```js untrusted run no-strict refresh
let x = 5;

alert(window.x); // undefined ("let" doesn't create a window property)
```

3. Also, all scripts share the same global scope, so variables declared in one `<script>` become visible in another ones:
Usamos `window` aqui, assumindo que nosso ambiente seja um navegador. Se o seu script puder ser executado em outros ambientes, é melhor utilizar o `globalThis`.

```html run
<script>
var a = 1;
let b = 2;
</script>
Todas as propriedades do objeto global podem ser acessadas diretamente:

<script>
alert(a); // 1
alert(b); // 2
</script>
```

4. And, a minor thing, but still: the value of `this` in the global scope is `window`.

```js untrusted run no-strict refresh
alert(this); // window
```

Why was it made like this? At the time of the language creation, the idea to merge multiple aspects into a single `window` object was to "make things simple". But since then many things changed. Tiny scripts became big applications that require proper architecture.

Is it good that different scripts (possibly from different sources) see variables of each other?

No, it's not, because it may lead to naming conflicts: the same variable name can be used in two scripts for different purposes, so they will conflict with each other.

As of now, the multi-purpose `window` is considered a design mistake in the language.

Luckily, there's a "road out of hell", called "JavaScript modules".

If we set `type="module"` attribute on a `<script>` tag, then such script is considered a separate "module" with its own top-level scope (lexical environment), not interfering with `window`.

- In a module, `var x` does not become a property of `window`:
```js run
alert("Olá");
// é o mesmo que
window.alert("Olá");
```

```html run
<script type="module">
var x = 5;
No navegador, funções e variáveis globais declaradas com `var` (não `let/const`!) tornam-se propriedades do objeto global:

alert(window.x); // undefined
</script>
```
```js run untrusted refresh
var gVar = 5;

- Two modules that do not see variables of each other:
alert(window.gVar); // 5 (se torna uma propriedade do objeto global)
```

```html run
<script type="module">
let x = 5;
</script>
Por favor, não confie nisso! Esse comportamento existe por motivos de compatibilidade. Scripts modernos usam [JavaScript modules](info:modules) onde tal coisa não acontece.

<script type="module">
alert(window.x); // undefined
alert(x); // Error: undeclared variable
</script>
```
Se usássemos `let`, isso não aconteceria:

- And, the last minor thing, the top-level value of `this` in a module is `undefined` (why should it be `window` anyway?):
```js run untrusted refresh
let gLet = 5;

```html run
<script type="module">
alert(this); // undefined
</script>
```
alert(window.gLet); // undefined (não se torna uma propriedade do objeto global)
```

**Using `<script type="module">` fixes the design flaw of the language by separating top-level scope from `window`.**
Se um valor é tão importante que você gostaria de deixá-lo disponível globalmente, escreva-o diretamente como uma propriedade.

We'll cover more features of modules later, in the chapter [](info:modules).
```js run
*!*
// tornando globais as informações de current user, para permitir que todos os script as acessem
window.currentUser = {
name: "John"
};
*/!*

// em outro lugar no código
alert(currentUser.name); // John

// ou, se tivermos um variável local com o nome "currentUser"
// a obtenha explicitamente do window (seguro!)
alert(window.currentUser.name); // John
```

## Valid uses of the global object
Dito isto, o uso de variáveis globais é geralmente desencorajado. Deve haver o menor número possível de variáveis globais. O design do código onde uma função recebe variáveis de entrada e produz certos resultados é mais claro, menos propenso a erros e mais fácil de testar do que se usar varáveis externas ou globais.

1. Using global variables is generally discouraged. There should be as few global variables as possible, but if we need to make something globally visible, we may want to put it into `window` (or `global` in Node.js).
## Usando para polyfills

Here we put the information about the current user into a global object, to be accessible from all other scripts:
Usamos o objeto global para testar o suporte aos recursos modernos da linguagem.

```js run
// explicitly assign it to `window`
window.currentUser = {
name: "John",
age: 30
};
Por exemplo, testar se o objeto `Promise` nativo existe (ele não existe em navegadores antigos):
```js run
if (!window.Promise) {
alert("Seu navegador é muito antigo!");
}
```

// then, elsewhere, in another script
alert(window.currentUser.name); // John
```
Se não houver (vamos dizer que estamos em um navegador antigo), podemos criar "polyfills": adicionar funções que não são suportadas pelo ambiente, mas existem no padrão moderno.

2. We can test the global object for support of modern language features.
```js run
if (!window.Promise) {
window.Promise = ... // implementação customizada do recurso moderno da linguagem
}
```

For instance, test if a build-in `Promise` object exists (it doesn't in really old browsers):
```js run
if (!window.Promise) {
alert("Your browser is really old!");
}
```
## Resumo

3. We can create "polyfills": add functions that are not supported by the environment (say, an old browser), but exist in the modern standard.
- O objeto global contém variáveis que devem estar disponíveis em qualquer lugar.

```js run
if (!window.Promise) {
window.Promise = ... // custom implementation of the modern language feature
}
```
Isso inclui objetos nativos Javascript, como `Array` e valores específicos do ambiente, como `window.innerHeight` -- a altura da janela no navegador.
- O objeto global tem o nome universal `globalThis`.

...And of course, if we're in a browser, using `window` to access browser window features (not as a global object) is completely fine.
...Porém é mais frequentemente referido pelos seu nomes específicos de ambientes "old-school", como `window` (navegador) e `global` (Node.js). Como `globalThis` é uma proposta recente, não é suportado pelo "non-Chromium Edge" (mas pode ser usado com um polyfill).
- Devemos salvar valores no objeto global apenas se eles forem realmente globais em nosso projeto. E manter sua quantidade no mínimo.
- No navegador, ao menos que estejamos usando [modules](info:modules), funções e variáveis globais declaradas com `var` tornam-se uma propriedade do objeto global.
- Para tornar nosso código à prova de mudanças no futuro e mais fácil de entender, devemos acessar as propriedades do objeto global diretamente, como `window.x`.