Herança e cadeia de protótipos (prototype chain) - JavaScript

Herança e cadeia de protótipos (prototype chain)
================================================

JavaScript é um pouco confuso para desenvolvedores com experiência em linguagens baseadas em classes (como Java ou C++), porque é dinâmico e não dispõe de uma implementação de uma `class` (a palavra-chave `class` foi introduzida no ES2015, mas é syntax sugar, o JavaScript permanece baseado em `prototype`).

Quando se trata de herança, o JavaScript tem somente um construtor: objetos. Cada objeto tem um link interno para um outro objeto chamado `prototype`. Esse objeto `prototype` também tem um atributo `prototype`, e assim por diante até o que o valor `null` seja encontrado como sendo o seu `prototype`. `null` que, por definição, não tem `prototype`, e age como um link final nesta **cadeia de protótipos** (prototype chain).

Isto muitas vezes é considerado como um dos pontos fracos do JavaScript, mas o modelo de herança prototipal é de fato mais potente do que o modelo clássico. É, por exemplo, relativamente trivial construir um "modelo clássico" (como na implementaçao de `class`), enquanto o contrário é uma tarefa muito mais difícil.

1 *N. da T: Como em uma implementação de fila em C, por exemplo.*

Herança com o encadeamento de protótipos
----------------------------------------

### Propriedades de heranças

Objetos em JavaScript são "sacos" dinâmicos de propriedades (a que se refere as próprias propriedades) e cada um tem um link para um objeto `prototype`. Eis o que acontece quando se tenta acessar uma propriedade:
```

// Vamos criar um objeto o da função f com suas próprias propriedades a e b:
let f = function () {
   this.a = 1;
   this.b = 2;
}
let o = new f(); // {a: 1, b: 2}

// adicionar propriedades no protótipo da função f
f.prototype.b = 3;
f.prototype.c = 4;

// não defina o protótipo f.prototype = {b: 3, c: 4}; isso vai quebrar a cadeia de protótipos
// o. [[Prototype]] possui propriedades bec.
// o. [[Prototype]]. [[Prototype]] é Object.prototype.
// Finalmente, o. [[Prototype]]. [[Prototype]]. [[Prototype]] é nulo.
// Este é o fim da cadeia de protótipos, como nulo,
// por definição, não possui [[Prototype]].
// Assim, a cadeia completa de protótipos se parece com:
// {a: 1, b: 2} ---> {b: 3, c: 4} ---> Object.prototype ---> null dfdf

console.log(o.a); // 1
// Existe uma propriedade 'a' no objeto o? Sim, e seu valor é 1.

console.log(o.b); // 2
// Existe uma propriedade própria 'b' em o? Sim, e seu valor é 2.
// O protótipo também tem uma propriedade 'b', mas não é visitado.
// Isso é chamado de sombreamento de propriedade(Property Shadowing)

console.log(o.c); // 4
// Existe uma propriedade própria 'c' em o? Não, verifique seu protótipo.
// Existe uma propriedade 'c' própria em o. [[Prototype]]? Sim, seu valor é 4.

console.log(o.d); // undefined
// Existe uma propriedade 'd' própria em o? Não, verifique seu prototype.
// Existe uma propriedade 'd' em o. [[Prototype]]? Não, verifique seu prototype.
// o. [[Prototype]]. [[Prototype]] é Object.prototype e não há propriedade 'd' por padrão, verifique seu prototype.
// o. [[Prototype]]. [[Prototype]]. [[Prototype]] é nulo, pare de pesquisar,
// nenhuma propriedade encontrada, retorne indefinido.
```

Code Link

Atribuir uma propriedade a um objeto cria uma propriedade nele. A única exceção às regras de obtenção e definição de comportamento é quando há uma propriedade herdada com um getter or a setter.

### Herança de "métodos"

JavaScript não tem "métodos" como os que conhecemos em linguagens baseadas em classes. Em JavaScript, qualquer função pode ser adicionada em um objeto em forma de propriedade. Uma herança de funções age como a herança de quaisquer outras propriedades que não sejam funções, e podemos inclusive realizar sobre-escrita de função (*method overriding*)!

Quando uma herança de função é executada, o valor de `this` aponta para o objeto que herdou as propriedades, não para o objeto prototype onde as propriedades foram escritas originalmente.

```js
var o = {
  a: 2,
  m: function (b) {
    return this.a + 1;
  },
};

console.log(o.m()); // 3
// Ao chamar 'o.m' neste caso, "this" refere-se a 'o'

var p = Object.create(o);
// 'p' é um objeto que foi herdado de 'o'

p.a = 12; // cria uma propriedade 'a' no objeto 'p'
console.log(p.m()); // 13
// Ao chamar 'p.m', 'this' refere-se a 'p'
// Então, quando 'p' herda a função de 'm' de 'o', 'this.a' representa 'p.a' que é a própria propriedade 'a' de 'p'
```

Maneiras de criar objetos e resultados dos protótipos encadeados
----------------------------------------------------------------

### Objetos criados com sintaxe de construtores

```js
var o = { a: 1 };

// O recém-criado objeto 'o' tem Object.prototype como o seu [[Prototype]]
// 'o' não tem uma propriedade chamada 'hasOwnProperty'
// hasOwnProperty é uma propriedade própria de Object.prototype. Então 'o' herda hasOwnProperty de Object.prototype

// Object.prototype tem null como seu protótipo.
// o ---> Object.prototype ---> null

var a = ["yo", "whadup", "?"];

// Arrays herdam de Array.prototype (que tem métodos como indexOf, forEach, etc.)
// A cadeia de protótipos se parece com isso:
// a ---> Array.prototype ---> Object.prototype ---> null

function f() {
  return 2;
}

// Funções herdam de Function.prototype (que tem métodos como call, bind, etc.)
// f ---> Function.prototype ---> Object.prototype ---> null
```

### Com um construtor

Um "construtor" em JavaScript é "somente" uma função que passa a ser chamada com o operador new.

```js
function Graph() {
  this.vertexes = [];
  this.edges = [];
}

Graph.prototype = {
  addVertex: function (v) {
    this.vertexes.push(v);
  },
};

var g = new Graph();
// 'g' é um objeto com as propriedades 'vertexes' e 'edges'.
// g.[[Prototype]] é o valor de Graph.prototype quando new Graph() é executada.
```

### Com Object.create

ECMAScript 5 introduziu o novo método: Object.create. Invocando este método podemos criar novos objetos. O prototype destes novos objetos é o primeiro argumento do método:

```js
var a = { a: 1 };
// a ---> Object.prototype ---> null

var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (inherited)

var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null

var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty); // undefined, porque não herda de Object.prototype
```

### Performance

O tempo de pesquisa para as propriedades que estão no alto da cadeia de protótipos pode ter um impacto negativo no desempenho, e isso pode ser significativo no código em que o desempenho é crítico. Além disso, tentar acessar propriedades inexistentes irá sempre atravessar a cadeia cheia do protótipo (full prototype chain).

Porém, quando estamos interagindo com as propriedades de um objeto, **toda** propriedade que está na cadeia do prototype (prototype chain) vai ser enumerada.

Para verificar se um objeto tem uma propriedade definida em si mesmo e não em algum lugar na sua cadeia de protótipo, é necessário usar o método `hasOwnProperty` que todos os objetos herdam do Object.prototype.

`hasOwnProperty` é a única alternativa em JavaScript que lida com propriedades sem atravessar a cadeia de protótipos.

**Nota:** Observação: **Não** é suficiente apenas verificar se o valor da propriedade é `undefined` para saber se ela existe. A propriedade pode muito bem existir e não ter sido inicializada, sendo assim o seu valor undefined.

### Má Pratica: Estender protótipos nativos

Um erro frequentemente cometido por programadores é estender um Object.prototype.

Esta técnica é chamada de "monkey patching" e quebra o encapsulamento. Não existe uma boa razão para desorganizar tipos nativos do JavaScript para adicionar uma nova funcionalidade ao mesmo.

O único bom motivo para estender um protótipo nativo do JavaScript é para dar suporte a novas "features" do JavaScript; por exemplo: Array.forEach, etc.

### Conclusão

É essencial entender bem "prototypal inheritance" antes de escrever códigos complexos. Tome cuidado com o tamanho da sua cadeia de protótipos, quebre a cadeia caso necessário para evitar problemas de performance. Nunca estenda protótipos nativos a menos que seja para conseguir compatibilidade com novas "features" do JavaScript.


Estrutura de dados do Javascript - JavaScript

Estrutura de dados do Javascript
================================

Todas as linguagens de programação têm estruturas de dados embutidas, mas geralmente diferem de uma linguagem para outra. Este artigo tenta listar as estruturas de dados internas disponíveis em JavaScript e quais propriedades elas possuem. Estes podem ser usados para construir outras estruturas de dados. Sempre que possível, são feitas comparações com outras línguas.

Tipagem dinâmica e fraca
------------------------

JavaScript é uma linguagem dinâmica com tipos dinâmicos. As variáveis em JavaScript não estão diretamente associadas a nenhum tipo de valor específico, e qualquer variável pode receber (e reatribuir) valores de todos os tipos:

```js
let foo = 42; // foo agora é um número
foo = "bar"; // foo agora é uma string
foo = true; // foo agora é um booleano
```

JavaScript também é uma linguagem de tipagem fraca, o que significa que permite a conversão implícita de tipo quando uma operação envolve tipos incompatíveis, em vez de gerar erros de tipo.

```js
const foo = 42; //foo é um número
const result = foo + "1"; // JavaScript coage foo para uma string, então ela pode ser concatenada com o outro operando
console.log(resultado); // 421
```

Coerções implícitas são muito convenientes, mas podem ser uma arma em potencial se os desenvolvedores não pretendem fazer a conversão ou pretendem converter na outra direção (por exemplo, string para número em vez de número para string). Para symbols e BigInts, o JavaScript desativou intencionalmente certas conversões de tipo implícito.

Tipos em JavaScript
-------------------

O conjunto de tipos na linguagem JavaScript consiste em *primitive values* e *objects*.

* Valores primitivos (dados imutáveis representados diretamente no nível mais baixo do idioma)
    + tipo Boolean
    + Tipo Null
    + Tipo Undefined
    + Tipo Number
    + tipo BigInt
    + tipo String
    + Tipo Symbol
* Objetos (coleções de propriedades)
Valores primitivos
------------------

Todos os tipos, exceto objetos, definem valores imutáveis (ou seja, valores que não podem ser alterados). Por exemplo, Strings são imutáveis. Referimo-nos a valores desses tipos como "*valores primitivos*".

### Tipo Boolean

Boolean representa uma entidade lógica e pode ter dois valores: `true` e `false`. Consulte Boolean e `Boolean` para obter mais detalhes.

### Tipo Null

O tipo Null tem exatamente um valor: `null`. Consulte `null` e Null para obter mais detalhes.

### Tipo Undefined

Uma variável que não recebeu um valor tem o valor `undefined`. Consulte `undefined` e Undefined para mais detalhes.

### Tipos numéricos

ECMAScript tem dois tipos numéricos integrados: Number e BigInt — junto com o valor relacionado NaN.

#### Tipo Number

O tipo Number é um valor IEEE 754 de formato binário de 64 bits de precisão dupla. É capaz de armazenar números de ponto flutuante positivos entre 2^-1074 (`Number.MIN_VALUE`) e 2^1024 (`Number.MAX_VALUE`), bem como números de ponto flutuante negativos entre -(2^-1074) e -(2^1024), mas só pode armazenar com segurança inteiros no intervalo -(2^53 − 1) (`Number.MIN_SAFE_INTEGER`) para 2^53 − 1 (`Number.MAX_SAFE_INTEGER`).

**Nota:** Você pode verificar se um número está dentro do intervalo de inteiros seguros usando `Number.isSafeInteger()`. Fora do intervalo de `Number.MIN_SAFE_INTEGER` a `Number.MAX_SAFE_INTEGER`, o JavaScript não pode mais representar inteiros com segurança; eles serão representados por uma aproximação de ponto flutuante de precisão dupla.

Valores fora do intervalo ±(2^-1074 a 2^1024) são convertidos automaticamente:

* Valores positivos maiores que `Number.MAX_VALUE` são convertidos em `+Infinity`.
* Valores positivos menores que `Number.MIN_VALUE` são convertidos em `+0`.
* Valores negativos menores que -`Number.MAX_VALUE` são convertidos para `-Infinity`.
* Valores negativos maiores que -`Number.MIN_VALUE` são convertidos para `-0`.

`+Infinity` e `-Infinity` se comportam de forma semelhante ao infinito matemático, mas com algumas pequenas diferenças; veja `Number.POSITIVE_INFINITY` e `Number.NEGATIVE_INFINITY` para detalhes.

O tipo Number tem apenas um inteiro com múltiplas representações: `0` é representado como `-0` e `+0` (onde `0` é um alias para `+0`). Na prática, quase não há diferença entre as diferentes representações; por exemplo, `+0 === -0` é `true`. No entanto, você pode perceber isso quando divide por zero:

```js
console.log(42 / +0); // Infinity
console.log(42 / -0); // -Infinity
```

Embora um número geralmente represente apenas seu valor, o JavaScript fornece operadores bitwise.

**Nota:** embora os operadores bit a bit *podem* ser usados para representar vários valores booleanos em um único número usando mascaramento de bits, isso geralmente é considerada uma má prática. JavaScript oferece outros meios para representar um conjunto de booleanos (como uma matriz de booleanos ou um objeto com valores booleanos atribuídos a propriedades nomeadas). O mascaramento de bits também tende a tornar o código mais difícil de ler, entender e manter.

Pode ser necessário usar essas técnicas em ambientes muito restritos, como ao tentar lidar com as limitações do armazenamento local ou em casos extremos (como quando cada bit na rede conta). Esta técnica só deve ser considerada quando for a última medida que pode ser tomada para otimizar o tamanho.

#### Tipo BigInt

O tipo BigInt é uma primitiva numérica em JavaScript que pode representar inteiros com precisão arbitrária. Com BigInts, você pode armazenar e operar com segurança em grandes números inteiros, mesmo além do limite de números inteiros seguros.

Um BigInt é criado anexando `n` ao final de um inteiro ou chamando o construtor.

Você pode obter o maior valor seguro que pode ser incrementado com Numbers usando a constante `Number.MAX_SAFE_INTEGER`. Com a introdução do BigInts, você pode operar com números além do `Number.MAX_SAFE_INTEGER`.

Este exemplo demonstra, onde incrementar o `Number.MAX_SAFE_INTEGER` retorna o resultado esperado:

```js
// BigInt
const x = BigInt(Number.MAX\_SAFE\_INTEGER); // 9007199254740991n
x + 1n === x + 2n; // false porque 9007199254740992n e 9007199254740993n são desiguais

// Number
Number.MAX\_SAFE\_INTEGER + 1 === Number.MAX\_SAFE\_INTEGER + 2; // true porque ambos são 9007199254740992
```

Você pode usar os operadores `+`, `*`, `-`, `**` e `%` com BigInts — assim como com Numbers. Um BigInt não é estritamente igual a um Number, mas é vagamente assim.

Um BigInt se comporta como um Number nos casos em que é convertido em booleano: `if`, `||`, `&&`, `Boolean`, `!`.

`BigInt`s não podem ser operados de forma intercambiável com Numbers. Em vez disso, um `TypeError` será lançado.

#### NaN

`NaN` ("**N**ot a **N**umber") é normalmente encontrado quando o resultado de uma operação aritmética não pode ser expresso como um número. É também o único valor em JavaScript que não é igual a si mesmo.

### Tipo String

O tipo String do JavaScript é usado para representar dados textuais. É um conjunto de "elementos" de valores inteiros sem sinal de 16 bits. Cada elemento na String ocupa uma posição na String. O primeiro elemento está no índice `0`, o próximo no índice `1` e assim por diante. O comprimento de uma String é o número de elementos nela.

As strings JavaScript são imutáveis. Isso significa que uma vez que uma string é criada, não é possível modificá-la.

No entanto, ainda é possível criar outra string com base em uma operação na string original. Por exemplo:

* Uma substring do original escolhendo letras individuais ou usando `substring()`.
* Uma concatenação de duas strings usando o operador de concatenação (`+`) ou `concat()`.

#### Cuidado com a tipagem do seu código!

Pode ser tentador usar strings para representar dados complexos. Fazer isso traz benefícios a curto prazo:

* É fácil construir strings complexas com concatenação.
* Strings são fáceis de depurar (o que você vê impresso é sempre o que está na string).
* Strings são o denominador comum de muitas APIs (campos de entrada, valores de armazenamento local , `XMLHttpRequest` respostas ao usar `responseText`, etc.) e pode ser tentador trabalhar apenas com strings.

Com convenções, é possível representar qualquer estrutura de dados em uma string. Isso não faz com que seja uma boa ideia. Por exemplo, com um separador, pode-se emular uma lista (enquanto um array JavaScript seria mais adequado). Infelizmente, quando o separador é usado em um dos elementos da "lista", a lista é quebrada. Um caractere de escape pode ser escolhido, etc. Tudo isso requer convenções e cria uma carga de manutenção desnecessária.

Use strings para dados textuais. Ao representar dados complexos, *parse* strings e use a abstração apropriada.

### Tipo Symbol

Um Symbol é um valor primitivo **único** e **imutável** e pode ser usado como a chave de uma propriedade Object (veja abaixo). Em algumas linguagens de programação, os símbolos são chamados de "átomos".

Para mais detalhes veja a página de referência `Symbol`.

Objetos
-------

Na ciência da computação, um objeto é um valor na memória que possivelmente é referenciado por um identificador.

### Propriedades

Em JavaScript, os objetos podem ser vistos como uma coleção de propriedades. Com a sintaxe literal de objeto, um conjunto limitado de propriedades é inicializado; então as propriedades podem ser adicionadas e removidas. Os valores de propriedade podem ser valores de qualquer tipo, incluindo outros objetos, o que permite construir estruturas de dados complexas. As propriedades são identificadas usando valores *key*. Um valor *key* é um String value ou um Symbol value.

Existem dois tipos de propriedades de objeto: A *data* property e a *accessor* property. Cada propriedade tem *attributes* correspondentes. Cada atributo é acessado internamente pelo mecanismo JavaScript, mas você pode defini-los por meio de `Object.defineProperty()` ou lê-los por meio de `Object.getOwnPropertyDescriptor()`. Você pode ler mais sobre as várias nuances na página `Object.defineProperty()`.

#### Propriedade de dados

As propriedades de dados associam uma chave a um valor. Pode ser descrito pelos seguintes atributos:

`value`

O valor recuperado por um acesso get da propriedade. Pode ser qualquer valor JavaScript.

`gravável`

Um valor booleano que indica se a propriedade pode ser alterada com uma atribuição.

`enumerável`

Um valor booleano que indica se a propriedade pode ser enumerada por um loop `for...in`. Consulte também Enumerabilidade e propriedade de propriedades para saber como a enumerabilidade interage com outras funções e sintaxes.

`configurável`

Um valor booleano que indica se a propriedade pode ser excluída, pode ser alterada para uma propriedade acessora e pode ter seus atributos alterados.

#### Propriedade do acessor

Associa uma chave com uma das duas funções de acesso (`get` e `set`) para recuperar ou armazenar um valor.

**Nota:** É importante reconhecer que é o acessor *property* — não o acessor *method*. Podemos fornecer acessores semelhantes a classes a um objeto JavaScript usando uma função como valor — mas isso não torna o objeto uma classe.

Uma propriedade do acessor tem os seguintes atributos:

`get`

Uma função chamada com uma lista de argumentos vazia para recuperar o valor da propriedade sempre que um acesso de obtenção ao valor for executado. Consulte também getters. Pode ser `indefinido`.

`definir`

Uma função chamada com um argumento que contém o valor atribuído. Executado sempre que se tenta alterar uma propriedade especificada. Consulte também setters. Pode ser `indefinido`.

`enumerável`

Um valor booleano que indica se a propriedade pode ser enumerada por um loop `for...in`. Consulte também Enumerabilidade e propriedade de propriedades para saber como a enumerabilidade interage com outras funções e sintaxes.

`configurável`

Um valor booleano que indica se a propriedade pode ser excluída, pode ser alterada para uma propriedade de dados e pode ter seus atributos alterados.

### Objetos e funções "normais"

Um objeto JavaScript é um mapeamento entre *keys* e *values*. Chaves são strings (ou símbolos), e *values* pode ser qualquer coisa. Isso torna os objetos um ajuste natural para hashmaps.

Funções são objetos regulares com a capacidade adicional de serem *callable*.

### Datas

Ao representar datas, a melhor opção é usar o utilitário `Date` integrado em JavaScript.

### Coleções indexadas: Arrays e Arrays tipados

Arrays são objetos regulares para os quais existe uma relação específica entre propriedades de chave inteira e a propriedade `length`.

Além disso, arrays herdam de `Array.prototype`, que fornece a eles um punhado de métodos convenientes para manipular arrays. Por exemplo, `indexOf()` (pesquisando um valor no array) ou [`push()`](/en- US/docs/Web/JavaScript/Reference/Global\_Objects/Array/push) (adicionando um elemento à matriz) e assim por diante. Isso torna os Arrays um candidato perfeito para representar listas ou conjuntos.

Typed Arrays apresentam uma visão semelhante a um array de um buffer de dados binários subjacente e oferecem muitos métodos que têm semântica semelhante aos equivalentes de array. "Typed array" é um termo abrangente para uma variedade de estruturas de dados, incluindo `Int8Array`, `Float32Array`, etc. Verifique a página typed array para obter mais informações .

### Coleções chaveadas: Maps, Sets, WeakMaps, WeakSets

Essas estruturas de dados usam referências de objetos como chaves. `Set` e `WeakSet` representante reenviam um conjunto de objetos, enquanto `Map` e `WeakMap` associam um valor a um objeto.

A diferença entre `Map`s e `WeakMap`s é que no primeiro, as chaves de objeto podem ser enumeradas. Isso permite otimizações de coleta de lixo no último caso.

Você pode implementar `Map`s e `Set`s você mesmo. No entanto, como os objetos não podem ser comparados (no sentido de `<` "menor que", por exemplo), nem o mecanismo expõe sua função de hash para objetos, o desempenho da pesquisa seria necessariamente linear. Implementações nativas deles (incluindo `WeakMap`s) podem ter um desempenho de pesquisa que é aproximadamente logarítmico para tempo constante.

Normalmente, para vincular dados a um nó DOM, pode-se definir propriedades diretamente no objeto ou usar atributos `data-*`. Isso tem a desvantagem de que os dados estão disponíveis para qualquer script em execução no mesmo contexto. `Map`s e `WeakMap`s facilitam *privately* vincular dados a um objeto.

### Dados estruturados: JSON

JSON (**J**ava**S**cript **O**bject **N**otation) é um formato leve de intercâmbio de dados, derivado do JavaScript, mas usado por muitas linguagens de programação. JSON cria estruturas de dados universais.

Consulte JSON e `JSON` para obter mais detalhes.

### Mais objetos na biblioteca padrão

JavaScript tem uma biblioteca padrão de objetos internos.

Por favor, dê uma olhada na referência para saber mais sobre objetos.

Determinando tipos usando o operador `typeof`
---------------------------------------------

O operador `typeof` pode ajudá-lo a encontrar o tipo de sua variável.

Leia a página de referência para obter mais detalhes e casos extremos.

Veja também
-----------

* Estruturas de dados e algoritmos JavaScript por Oleksii Trekhleb
* Coleção de Nicholas Zakas de estrutura de dados comum e algoritmos comuns em JavaScript.
* Search Tre(i)es implementados em JavaScript
* Tipos de dados e valores na especificação ECMAScript


Referência JavaScript - JavaScript

Referência JavaScript
=====================

Sobre essa Referência
---------------------

 A referência de JavaScript serve como um repositório para fatos sobre a linguagem JavaScript. A linguagem é inteiramente descrita aqui em detalhes. Quando você escreve códigos fontes em JavaScript, muitas vezes você irá precisar de referências ( por isto o titulo "Referência de JavaScript" ). Se você estiver aprendendo sobre JavaScript, ou precisa de ajuda para entender alguma das suas capacidades ou recursos, você pode conferir o Guia de JavaScript !
 O JavaScript é uma linguagem interpretada que se destina a ser utilizado dentro de algum ambiente maior, seja ele um script de um navegador, do lado do servidor, ou algo similar. Para a maior parte, esta referência se distinta à um ambiente agnóstico, e não somente ao ambiente de um navegador.

Onde encontrar mais informações sobre JavaScript ?
--------------------------------------------------

Você pode verificar a documentação do *core* da linguagem e seus novos recursos ( ECMAScript puro em sua maior parte), incluindo também :

* Guia de JavaScript
* Referência de JavaScript

Se você é novo com JavaScript, recomendamos à você começar com o guia. Uma vez que você já tenha uma base sobre os fundamentos da linguagem, você pode usar a referência para obter mais detalhes sobre objetos individuais e construtores da linguagem.

Estrutura da referência
-----------------------

Na referência do JavaScript você poderá encontrar os seguintes seções :

Padrões de objetos internos (*built-in objects*)

Esta seção documenta todos o padrão JavaScript de objetos internos, juntamente com seus métodos e propriedades.

Instruções e Declarações (*Statements*)

As aplicações em JavaScript consistem em declarações com uma sintaxe apropriada. Uma única declaração pode abranger várias linhas de código. Várias instruções podem ocorrer em uma única linha também, se cada declaração for devidamente separada por ponto e virgula. Instrução não é uma palavra-chave, mas sim, um grupo de palavras-chave.

Expressões e operadores

Esta seção documenta todos os operadores da linguagem JavaScript, expressões e palavras-chave.

Funções

Esta seção é referente as funções existentes no JavaScript.

Novo no JavaScript

Esta seção é sobre as versões do JavaScript, contendo o histórico de versões e o que há de novo nas proximas versões.

### Mais paginas de referências

* Recursos e funcionalidades obsoletas
* Gramática Léxica
* Tipos e estruturas de dados
Objetos Globais
---------------

{{page('/pt-BR/docs/JavaScript/Reference/Global\_Objects', 'Standard global objects (by category)')}}Funções e escopo de função (en-US)
----------------------------------

* `argumentos` (en-US)
* Modo Strict (en-US)
Declarações
-----------

Aplicações em JavaScript são realizadas através de instruções com uma sintaxe apropriada. Uma única instrução pode abranger multiplas linhas. Multiplas instruções podem estar contidas em uma única linha se cada instrução estiver separada por ponto e vírgula ( ; ).

Instruções e declarações por categoria
--------------------------------------

Para visualizar em ordem alfabética use a barra de rolagem à esquerda.

### Control flow

`Block`

Uma instrução de bloqueio é usada para um grupo de zero ou mais instruções. O bloqueio é delimitado por um par de chaves.

`break`

Termina o atual loop, troca, ou nomeia instruções e transfere o controle do programa para a próxima instrução após a que foi terminada agora.

`continue`

Termina a execução das instruções na atual iteração do atual loop, e continua a execução do loop com a seguinte iteração.

`Empty`

Uma instrução vazia é usada para gerar uma "não-instrução", ainda que o JavaScrpit espere uma.

`if...else`

Executa uma instrução se a condição especificada é verdadeira. Se a condição é falsa, outra instrução pode ser executada.

`switch`

Retorna uma expressão, combinando o valor da expressão a condição do caso, e executa a condição associada a este caso.

`throw`

Aplica uma exceção definida pelo usuário.

`try...catch`

Marca um bloco de instruções para tentar, e especifica a resposta, uma exceção deve ser retornada.

### Declarações

`var`

Declara uma variável, opcionalmente inicializando com um valor.

Experimental `let`

Declara acesso ao local da variável, opcionalmente inicializando com um valor.

Experimental `const`

Declara uma constante de apenas leitura.

### Funções e classes

`function`

Declara uma função com os parâmetros especificos.

Experimental `function*`

Gera funções habilitando iteradores de escrita mais facilmente.

`return`

Especifica o valor a ser retornado por uma função.

Experimental `class`

Declara uma classe.

### Iterações

`do...while`

Cria um loop que executa uma especifica instrução até que a condição de teste seja falsa. A condição é retornada depois da execução da instrução, resultando na instrução especificada executando ao menos uma vez.

`for`

Cria um loop que consiste em três opções de expressões, entre parenteses e separado por ponto e vírgula, seguido pela instrução executada no loop.

Deprecated
Non-standard
 `for each...in`

Itera uma variável especificada sobre todos os valores das propriedades do objeto. Para cada propriedade distinta, uma instrução especificada é executada.

`for...in`

Itera através de enumeráveis propriedades de um objeto, em ordem arbitrária. Para cada propriedade distinta, instruções podem ser executadas.

Experimental `for...of`

Itera através de objetos iteráveis (incluindo arrays, array-like objects, iterators and generators (en-US)), invocando uma iteração personalizada com instruções para serem executadas pelo valor de cada propriedade.

`while`

Cria um loop que executa uma especifica instrução enquanto o teste da condição for positivo. A condição é retornada antes de executar a instrução.

### Outros

`debugger`

Invoca qualquer funcionalidade de depuração disponível. Se não há funcionabilidade disponível, a instrução não tem efeito.

Experimental `export`

Usado para exportar funções que os deixa disponível para importação em módulos externos, outros scripts.

Experimental `import`

Usado para importar funções exportadas de um módulo externo, outro script.

`label`

Fornece uma instrução com um identificador que pode ser referido usando `break` ou `continue` instruções.

Deprecated `with`

Extende o alcance de uma instrução.

Veja também
-----------

* Operators
Operadores e outras palavras-chave
----------------------------------

Este capítulo documenta todos os operadores, expressões e keywords da linguagem JavaScript .

Expressões e operadores por categoria
-------------------------------------

Para uma lista alfabética ver a barra lateral à esquerda.

### Expressões primárias

Palavras-chave e expressões básicas em JavaScript.

`this`

A palavra-chave `this` refere-se ao contexto de execução da função.

`function`

A palavra-chave `function` define uma função.

Experimental `class`

A palavra-chave `class` define uma classe.

Experimental `function*`

A palavra-chave `function*` define um gerador de função.

Experimental `yield`

Pausa e retorma uma função de gerador

Experimental `yield*`

Delegar a outra função gerador ou objeto iterável.

`[]`

Array initializer/literal syntax.

`{}`

Object initializer/literal syntax.

`/ab+c/i`

Regular expression literal syntax.

Experimental `[for (x of y) x]` (en-US)

Array comprehensions.

Experimental `(for (x of y) y)` (en-US)

Generator comprehensions.

`( )`

Grouping operator.

### Left-hand-side expressions

Left values are the destination of an assignment.

Property accessors

 Member operators provide access to a property or method of an object
 (`object.property` and `object["property"]`).

`new`

The `new` operator creates an instance of a constructor.

Experimental `super`

The `super` keyword calls the parent constructor.

Experimental `...obj` (en-US)

The spread operator allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) are expected.

### Incremento e decremento

Operadores sufixo/prefixo para incremento e sufixo/prefixo para decremento.

`A++` (en-US)

Operador sufixo para incremento.

`A--` (en-US)

Operador sufixo para decremento.

`++A` (en-US)

Operador prefixo para incremento.

`--A` (en-US)

Operador prefixo para decremento.

### Unary operators

A unary operation is operation with only one operand.

`delete` (en-US)

The `delete` operator deletes a property from an object.

`void`

The `void` operator discards an expression's return value.

`typeof`

The `typeof` operator determines the type of a given object.

`+` (en-US)

The unary plus operator converts its operand to Number type.

`-` (en-US)

The unary negation operator converts its operand to Number type and then negates it.

`~` (en-US)

Bitwise NOT operator.

`!` (en-US)

Logical NOT operator.

### Operadores aritméticos

Arithmetic operators take numerical values (either literals or variables) as their operands and return a single numerical value.

`+` (en-US)

Operador de soma.

`-` (en-US)

Operador de subtração.

`/` (en-US)

Operador de divisão.

`*` (en-US)

Operador de multiplicação.

`%` (en-US)

Remainder operator.

### Operadores relacionais

A comparison operator compares its operands and returns a `Boolean` value based on whether the comparison is true.

`in`

The `in` operator determines whether an object has a given property.

`instanceof`

The `instanceof` operator determines whether an object is an instance of another object.

`<` (en-US)

Operador "menor que".

`>` (en-US)

Operador "maior que".

`<=` (en-US)

Operador "menor ou igual que".

`>=` (en-US)

Operador "maior ou igual que".

### Operadores de igualdade

O resultador de um operador de igualdade é do tipo `Booleano` baseado que a comparação seja verdadeira.

`==` (en-US)

Operadores de igualdade.

`!=` (en-US)

Inequality operator.

`===` (en-US)

Identity operator.

`!==` (en-US)

Nonidentity operator.

### Bitwise shift operators

Operations to shift all bits of the operand.

`<<` (en-US)

Bitwise left shift operator.

`>>` (en-US)

Bitwise right shift operator.

`>>>` (en-US)

Bitwise unsigned right shift operator.

### Binary bitwise operators

Bitwise operators treat their operands as a set of 32 bits (zeros and ones) and return standard JavaScript numerical values.

`&` (en-US)

Bitwise AND.

`|` (en-US)

Bitwise OR.

`^` (en-US)

Bitwise XOR.

### Operadores Lógicos Binários

Operadores lógicos são normalmente usados com boolean (logical) valores, e quando eles são, eles retornam um valor Boolean.

`&&` (en-US)

AND.

`||` (en-US)

OR.

### Operador de Condicional (ternário)

`(condition ? ifTrue : ifFalse)`

O operador condicional retorna um dos dois valores baseado no valor lógico da condição.

### Assignment operators

An assignment operator assigns a value to its left operand based on the value of its right operand.

`=` (en-US)

Assignment operator.

`*=` (en-US)

Multiplication assignment.

`/=` (en-US)

Division assignment.

`%=` (en-US)

Remainder assignment.

`+=` (en-US)

Addition assignment.

`-=` (en-US)

Subtraction assignment

`<<=` (en-US)

Left shift assignment.

`>>=` (en-US)

Right shift assignment.

`>>>=` (en-US)

Unsigned right shift assignment.

`&=` (en-US)

Bitwise AND assignment.

`^=` (en-US)

Bitwise XOR assignment.

`|=` (en-US)

Bitwise OR assignment.

Experimental
 `[a, b] = [1, 2]`

Experimental
 `{a, b} = {a:1, b:2}`

Destructuring assignment allows you to assign the properties of an array or object to variables using syntax that looks similar to array or object literals.

### Comma operator

`,`

The comma operator allows multiple expressions to be evaluated in a single statement and returns the result of the last expression.

### Non-standard features

Non-standard Legacy generator function (en-US)

The `function` keyword can be used to define a legacy generator function inside an expression. To make the function a legacy generator, the function body should contains at least one `yield` expression.

Non-standard Expression closures

The expression closure syntax is a shorthand for writing simple function.

Especificações
--------------

| Specification |
| --- |
| ECMAScript Language Specification # sec-addition-operator-plus |
| ECMAScript Language Specification # sec-assignment-operators |
| ECMAScript Language Specification # sec-async-function-definitions |
| ECMAScript Language Specification # sec-async-generator-function-definitions |
| ECMAScript Language Specification # prod-BitwiseANDExpression |
| ECMAScript Language Specification # sec-bitwise-not-operator |
| ECMAScript Language Specification # prod-BitwiseORExpression |
| ECMAScript Language Specification # prod-BitwiseXORExpression |
| ECMAScript Language Specification # sec-class-definitions |
| ECMAScript Language Specification # sec-comma-operator |
| ECMAScript Language Specification # sec-conditional-operator |
| ECMAScript Language Specification # sec-postfix-decrement-operator |
| ECMAScript Language Specification # sec-delete-operator |
| ECMAScript Language Specification # sec-destructuring-assignment |
| ECMAScript Language Specification # sec-destructuring-binding-patterns |
| ECMAScript Language Specification # sec-multiplicative-operators |
| ECMAScript Language Specification # sec-equality-operators |
| ECMAScript Language Specification # sec-exp-operator |
| ECMAScript Language Specification # sec-function-definitions |
| ECMAScript Language Specification # sec-generator-function-definitions |
| ECMAScript Language Specification # sec-relational-operators |
| ECMAScript Language Specification # sec-grouping-operator |
| ECMAScript Language Specification # sec-import-calls |
| ECMAScript Language Specification # prod-ImportMeta |
| HTML Standard # hostgetimportmetaproperties |
| ECMAScript Language Specification # sec-postfix-increment-operator |
| ECMAScript Language Specification # sec-left-shift-operator |
| ECMAScript Language Specification # prod-LogicalANDExpression |
| ECMAScript Language Specification # sec-logical-not-operator |
| ECMAScript Language Specification # prod-LogicalORExpression |
| ECMAScript Language Specification # sec-new-operator |
| ECMAScript Language Specification # sec-built-in-function-objects |
| ECMAScript Language Specification # sec-null-value |
| ECMAScript Language Specification # prod-CoalesceExpression |
| ECMAScript Language Specification # sec-object-initializer |
| ECMAScript Language Specification # prod-OptionalExpression |
| ECMAScript Language Specification # sec-property-accessors |
| ECMAScript Language Specification # sec-signed-right-shift-operator |
| ECMAScript Language Specification # prod-SpreadElement |
| ECMAScript Language Specification # prod-ArgumentList |
| ECMAScript Language Specification # prod-PropertyDefinition |
| ECMAScript Language Specification # sec-subtraction-operator-minus |
| ECMAScript Language Specification # sec-super-keyword |
| ECMAScript Language Specification # sec-this-keyword |
| ECMAScript Language Specification # sec-typeof-operator |
| ECMAScript Language Specification # sec-unary-minus-operator |
| ECMAScript Language Specification # sec-unary-plus-operator |
| ECMAScript Language Specification # sec-unsigned-right-shift-operator |
| ECMAScript Language Specification # sec-void-operator |
| ECMAScript Language Specification # prod-YieldExpression |
| ECMAScript Language Specification # sec-generator-function-definitions-runtime-semantics-evaluation |

Veja também
-----------

* Operator precedence
Comentários
-----------

* Comentários de código (en-US) (`//` and `/* */`)
E4X (extensão)
Deprecated
-------------------------

Declarações Globais:

* default XML namespace

Funções Globais:

* isXMLName()

Construtores Globais:

* Namespace()
* QName()
* XML()
* XMLList()
Apêndice A - Palavras Reservadas (en-US)
----------------------------------------

Apêndice B - Funcionalidades Obsoletas (en-US)
----------------------------------------------


Modelo de Concorrência e Event Loop - JavaScript

Modelo de Concorrência e Event Loop
===================================

O JavaScript possui um modelo de concorrência baseado em um **event loop** (laço de eventos), em português), responsável pela execução do código, coleta e processamento de eventos e execução de subtarefas enfileiradas. Este modelo é bem diferente de outras linguagens, como C ou Java, por exemplo.

Conceitos de runtime (tempo de execução)
----------------------------------------

Os próximos tópicos irão explicar teoricamente o modelo. Interpretadores modernos de JavaScript implementam e otimizam fortemente as semânticas descritas.

### Representação visual

![Stack, heap, queue](/pt-BR/docs/Web/JavaScript/Event_loop/the_javascript_runtime_environment_example.svg)

### Pilha (Stack)

As chamadas de funções criam uma pilha de *frames* (quadros).

```js
function foo(b) {
  let a = 10;
  return a + b + 11;
}

function bar(x) {
  let y = 3;
  return foo(x \* y);
}

const baz = bar(7); // atribui 42 a baz
```

Ordem das operações:

1. Quando chamamos a função `bar`, o primeiro *frame* é criado contendo argumentos e variáveis locais de `bar`.
2. Quando a função `bar` chama `foo`, o segundo *frame* é criado e é colocado no topo da pilha, contendo os argumentos e as variáveis locais de `foo`.
3. Quando `foo` retorna, o *frame* do topo é removido da pilha (deixando apenas o *frame* da chamada de `bar`).
4. Quando `bar` retorna, a pilha fica vazia.

Note que os argumentos e variáveis locais podem continuar existindo, pois são armazenados fora da pilha — de forma que podem ser acessados por quaisquer funções aninhadas muito depois de sua função externa ter retornado.

### Acervo (Heap)

Os objetos são alocados em um *heap* (acervo), que é apenas um nome para denotar uma grande região não estruturada da memória.

### Fila (Queue)

O *runtime* do JavaScript contém uma fila de mensagens, que é uma lista de mensagens a serem processadas. Cada mensagem é associada a uma função, que é chamada para lidar com a mensagem.

Em algum ponto durante o *event loop* (laço de eventos), o *runtime* começa a manipular as mensagens na fila, começando pela mais antiga. Para fazer isso, a mensagem é removida da fila e sua função correspondente é chamada com a mensagem como um parâmetro de *input* (entrada). Como de costume, chamar uma função cria um novo *frame* (quadro) na pilha para uso dessa função.

O processamento de funções continua até que a pilha fique novamente vazia, então o *event loop* processará a próxima mensagem na fila (se houver uma).

Laço de Eventos (Event loop)
----------------------------

O ***Event loop*** tem esse nome por causa da forma que normalmente é implementado, que se assemelha a:

```js
while (queue.waitForMessage()) {
  queue.processNextMessage();
}
```

`queue.waitForMessage` aguarda, de maneira síncrona, receber uma mensagem (se não houver nenhuma já disponível esperando para ser tratada).

### Processamento Completo ("Run-to-completion")

Cada mensagem é processada completamente antes de outra mensagem ser processada. Isso oferece um bom fundamento ao pensar sobre o seu *software*, incluindo o fato de que, independente de quando uma função é executada, ela não pode ser interrompida e, portanto, será executada por completo antes que outro código rode (e modifique dados manipuláveis pela função). Isso é diferente do C, por exemplo, no qual uma função que está sendo executada em uma *thread* (um fluxo de execução), pode ser interrompida a qualquer momento para executar um outro código em outra *thread*.

Um aspecto negativo deste modelo é que se uma mensagem levar muito tempo para ser finalizada, a aplicação web ficará indisponível para processar as interações do usuário, como cliques ou rolagens. O navegador mitiga este problema através do aviso: "*Um script desta página pode estar ocupado, ou parou de responder*". Uma boa prática a seguir é fazer o processamento de mensagens curtas, e, se possível, dividir uma longa mensagem em múltiplas mensagens menores.

### Adicionando mensagens

Nos navegadores, as mensagens são adicionadas a qualquer momento que um evento é acionado se este possuir um *listener* (ouvinte). Caso não haja, o evento será ignorado. Assim, um clique em um elemento com um manipulador de eventos de clique adicionará uma mensagem, como qualquer outro evento.

A função `setTimeout` (en-US) é chamada com 2 argumentos: uma mensagem para adicionar à fila (queue) e um valor em tempo (opcional, o padrão é `0`). O valor de tempo (*time value*) representa o intervalo (mínimo) com que a mensagem será realmente enviada à fila. Se não houver outra mensagem na fila, a mensagem será processada logo após o intervalo. No entanto, caso haja mensagens, a mensagem `setTimeout` terá que esperar até que outras mensagens sejam processadas. Por esse motivo, o segundo argumento indica um tempo *mínimo* e não um tempo *garantido*.

Aqui está um exemplo que demonstra esse conceito (`setTimeout` não é executado imediatamente após o temporizador expirar):

```js
const s = new Date().getSeconds();

setTimeout(function () {
  // imprime "2", o que significa que o callback não é chamado imediatamente após 500 milissegundos.
  console.log("Ran after " + (new Date().getSeconds() - s) + " seconds");
}, 500);

while (true) {
  if (new Date().getSeconds() - s >= 2) {
    console.log("Good, looped for 2 seconds");
    break;
  }
}
```

### Intervalos de zero segundos

O intervalo zero não significa, necessariamente, que o *callback* será disparado após zero milissegundos. Chamar `setTimeout` (en-US) com um intervalo de `0` (zero) milissegundos não executa a função do *callback* após intervalo dado.

A execução depende do número de mensagens em espera na fila. No exemplo abaixo, a mensagem `''this is just a message''` será escrita no console antes que a mensagem do *callback* seja processada, porque, como informado previamente, o intervalo definido na função indica o tempo *mínimo* necessário para que a aplicação processe a requisição e não o tempo *exato* de processamento.

Basicamente, `setTimeout` precisa esperar que todo o código das mensagens enfileiradas seja concluído, mesmo que você tenha especificado um tempo limite específico para o seu `setTimeout`.

```js
(function () {
  console.log("this is the start");

  setTimeout(function cb() {
    console.log("Callback 1: this is a msg from call back");
  }); // tem um valor de tempo padrão de 0

  console.log("this is just a message");

  setTimeout(function cb1() {
    console.log("Callback 2: this is a msg from call back");
  }, 0);

  console.log("this is the end");
})();

// "this is the start"
// "this is just a message"
// "this is the end"
// "Callback 1: this is a msg from call back"
// "Callback 2: this is a msg from call back"
```

### Múltiplos *runtimes* comunicando-se em conjunto

Um *web worker* ou um `iframe` com uma diferente origem (cross-origin) tem seu próprio *stack*, *heap* e *queue* de messagens. Dois *runtimes* distintos só podem se comunicar por meio do envio de mensagens via método `postMessage` (en-US). Este método adiciona uma mensagem ao outro *runtime*, se este escutar os eventos de `message`.

Sem bloqueio
------------

Uma propriedade muito interessante do modelo *event loop* é que o JavaScript, ao contrário de muitas outras linguagens, nunca bloqueia. A manipulação de E/S (*I/O*) é tipicamente realizada através de eventos e *callbacks*. Portanto, quando uma aplicação está esperando pelo retorno de uma consulta do IndexedDB ou de uma requisição XHR, ela ainda pode processar outras coisas, como as ações do usuário.

Exceções de legado existem, como por exemplo, `alert` ou XHR síncrono, mas é considerado uma boa prática evitá-los. Tome cuidado, exceções a exceção existem (mas geralmente são, mais do que qualquer coisa, *bugs* de implementação).

Veja também
-----------

* Event loops no HTML standard
* Node.js Event Loop


Gerenciamento de Memória - JavaScript

Gerenciamento de Memória
========================

Introdução
----------

Linguagens de baixo nível, como C, tem primitivas de gerenciamento de memória de baixo nível como `malloc()` e `free()`. Em contrapartida, os valores do JavaScript são alocados quando coisas (objetos, strings, etc.) são criadas e "automaticamente" liberadas quando não são mais usadas. Este último processo se chama *garbage collection*. Facilmente se torna uma fonte de confusão e dá a impressão aos desenvolvedores JavaScript (e outras linguagens de alto nível) que eles não precisam se preocupar com o consumo de memória. Isto é um erro.

Ciclo de vida da memória
------------------------

Independentemente da linguagem de programação, o ciclo de vida da memória é praticamente sempre o mesmo:

1. Alocar a memória que você precisa
2. Utilizar a memória alocada (ler, escrever)
3. Liberar a memória alocada quando não é mais necessária

A primeira e a segunda parte são explícitas em todas as linguagens. A última parte é explicita em linguagens de baixo nível, porém implícito em linguagens de alto nível como JavaScript.

### Alocação no JavaScript

#### Inicialização de valor

A fim de não incomodar o programador com alocações, o JavaScript faz isso com os valores conforme são declarados.

```js
var n = 123; // aloca memória para um número
var s = "azerty"; // aloca memória para uma string

var o = {
  a: 1,
  b: null,
}; // aloca memória para um objeto e seus valores contidos

// (assim como o objeto) aloca memória para o vetor e
// seus valores contidos
var a = [1, null, "abra"];

function f(a) {
  return a + 2;
} // aloca uma função (que é um objeto que pode ser chamado)

// expressões de funções também alocam um objeto
someElement.addEventListener(
  "click",
  function () {
    someElement.style.backgroundColor = "blue";
  },
  false,
);
```

#### Alocação via chamada de uma função

Algumas funções quando chamadas resultam na alocação de um objeto.

```js
var d = new Date();
// aloca um elemento do DOM
var e = document.createElement("div");
```

Alguns métodos alocam novos valores ou objetos:

```js
var s = "azerty";
var s2 = s.substr(0, 3); // s2 é uma nova string
// Como as strings são valores imutáveis,
// o JavaScript pode decidir não alocar memória,
// mas apenas armazenar o intervalo [0, 3].

var a = ["ouais ouais", "nan nan"];
var a2 = ["generation", "nan nan"];
var a3 = a.concat(a2);
// novo vetor com 4 elementos sendo
// a concatenação dos elementos a e a2
```

### Utilização de valores

A utilização de valores basicamente significa leitura e escrita em memória alocada. Isto pode ser feito ao ler ou escrever o valor de uma variável ou a propriedade de um objeto ou até mesmo ao passar um argumento para uma função.

### Libere quando a memória não for mais necessária

A maioria dos problemas relacionados ao gerenciamento de memória aparecem nesta fase. A tarefa mais complicada aqui é descobrir quando "a memória alocada não é mais necessária". Geralmente exige que o desenvolvedor determine a onde no programa tal pedaço da memória não é mais necessária e liberá-la.

Linguagens de alto nível vêm com um pedaço de software chamado "garbage collector" (coletor de sujeira), cujo trabalho é monitorar a alocação de memória a fim de descobrir quando um pedaço de código não é mais necessário e neste caso, automaticamente liberá-lo. Este processo é algo aproximado já que, em geral, saber se um pedaço de memória é necessário é algo indecidível (que não pode ser resolvido através de um algoritmo).

Garbage collection
------------------

Como foi mencionado acima, em geral o problema de automaticamente descobrir se a memória "não é mais necessária" é indecidível. Como consequência, os *garbage collections* implementam uma limitação de uma solução ao problema em geral. Esta seção irá explicar os conceitos necessários para entender os principais algoritmos de garbage collection e suas limitações.

### Referências

O principal conceito de algoritmos do garbage collection depende do conceito de *referência*. Dentro do contexto de gerenciamento de memória, é dito que um objeto faz referência a outro, caso o primeiro tenha acesso a este último (de maneira implícita ou explícita). Por exemplo, um objeto JavaScript tem uma referência ao seu prototype (referência implícita) e para os valores de suas propriedades (referência explícita).

Neste contexto, o conceito de "objeto" se extende para algo mais abrangente do que os objetos comuns do JavaScript, e também contém escopos de função (ou o escopo lexical global).

### Referência de contagem do garbage collection

Este é o algoritmo mais ingênuo de garbage collection. este algoritmo reduz a definição de "um objeto não mais necessário" para "um objeto não tem outro objeto referenciando ele". Um objeto pode ser coletado pelo garbage collector se não existir referência apontando para este objeto.

#### Exemplo

```js
var o = {
  a: {
    b: 2,
  },
};
// 2 objetos são criados. Um é referenciado pelo outro como uma de suas propriedades.
// O outro é referenciado pelo fato de ser atribuído à variável 'o'.
// Obviamente, nenhum pode ser coletado pelo garbage collector

var o2 = o; // a varável 'o2' é a segunda coisa que tem
// uma referência ao objeto
o = 1; // agora, o objeto que estava originalmente no 'o'
// tem uma referência única
// encorporada pela variável 'o2'

var oa = o2.a; // Referência para a propriedade 'a' do objeto.
// Este objeto agora tem 2 referências: uma como uma propriedade,
// a outra como a variável 'oa'

o2 = "yo"; // O objeto que estava originalmente em 'o' agora não tem
// nenhuma referência para ele.
// Ele poderia ser coletado pelo garbage collector.
// Entretanto o que era sua propriedade 'a' continua sendo referenciada
// pela variável 'oa', então ele não pode ser coletado.

oa = null; // O que era a propriedade 'a' do objeto original em 'o'
// não tem mais refêrencia para ele. Então pode ser coletado.
```

#### Limitação : ciclos

Esse algoritmo ingênuo tem a limitação de que objetos que referenciam um ao outro (e formam um ciclo), podem ser "não mais necessários" e ainda assim não serem coletados.

```js
function f() {
  var o = {};
  var o2 = {};
  o.a = o2; // o referencia o2
  o2.a = o; // o2 referencia o

  return "azerty";
}

f();
// Dois objetos são criados e referenciam um ao outro criando assim um ciclo.
// Eles não vão sair do escopo da função depois dela ser chamada, então eles
// são efetivamente inúteis e podem ser liberados.
// Entretanto, o algoritmo contador de referências considera que desde que ambos
// os objetos sejam referenciados pelo menos uma vez,
// nenhum deles podem ser coletados.
```

#### Exemplo da vida real

Internet Explorer 6 e 7 são conhecidos por terem um coletor com contador de referências para os objetos do DOM. Ciclos são um erro comum que podem gerar erros na memória:

```js
var div;
window.onload = function () {
  div = document.getElementById("minhaDiv");
  div.referenciaCircular = div;
  div.muitosDados = new Array(10000).join("\*");
};
```

No exemplo acima, o elemento do DOM "minhaDiv" tem uma referência circular para ela mesma na propriedade "referenciaCircular". Se a propriedade não for removida ou anulada explicitamente, o contador de referências do coletor sempre terá pelo menos uma referência intacta e irá manter o elemento do DOM na memória mesmo se ele for removido da árvore do DOM. Se o elemento do DOM retém muitos dados (ilustrado no exemplo acima com a propriedade "muitosDados"), a memória consumida por esses dados não será liberada.

### Algoritmo de varredura e rotulação

Esse algoritmo reduz a definição de "um objeto não é mais necessário" para "um objeto é inacessível".

Esse algoritmo assume o conhecimento de uma lista de objetos chamada *roots* (raízes) (no JavaScript, o root é o objeto global). Periodicamente, o coletor iniciará por esses roots, encontrando todos os objetos que são referenciados por esses roots, então todos os objetos referenciados por eles, etc. Começando pelos roots, o coletor encontrará todos os objetos acessíveis e coletará todos os objetos inacessíveis.

Esse algoritmo é melhor que o anterior pois "um objeto que não tem referência" leva a esse objeto inacessível. O oposto não é verdadeiro como nós vimos com os ciclos.

A partir de 2012, todos os navegadores modernos vem com um coletor com varredura e rotulação. Todas as melhorias feitas nessa área do coletor do JavaScript (geracional/incremental/concorrência/coletor paralelo) nos últimos anos são implementações melhoradas deste algoritmo, mas não melhorias para o coletor propriamente nem a redução da definição de quando "um objeto não é mais necessário".

#### Ciclos não são mais um problema

No primeiro exemplo, depois do retorno da chamada da função, os 2 objetos não são mais referenciados por algo acessível pelo objeto global. Consequentemente, eles não serão acessíveis pelo coletor.

A mesma coisa acontece com o segundo exemplo. Uma vez que o div e o seu gerenciador de eventos se tornem inacessíveis pelos roots, ambos podem ser coletados, apesar de referenciar um ao outro.

#### Limitação: objetos devem ser feitos explicitamente inacessíveis

Apesar disso ser marcado como uma limitação, isso é algo raro na prática e é por isso que ninguém se importa muito sobre o coletor.

Veja também
-----------

* IBM article on "Memory leak patterns in JavaScript" (2007)
* Kangax article on how to register event handler and avoid memory leaks (2010)
* Performance


Comparações de igualdade e uniformidade - JavaScript

Comparações de igualdade e uniformidade
=======================================

JavaScript fornece três diferentes operações de comparação de valores:

* igualdade estrita (ou "três iguais" ou "identidade") usando === (en-US),
* igualdade ampla ("dois iguais") usando == (en-US),
* e `Object.is` (novo no ECMAScript 6).

A escolha de qual operação usar depende da ordem de comparação que você está procurando executar.

Em resumo, dois iguais irá realizar uma conversão de tipo ao comparar duas coisas; três iguais irá fazer a mesma comparação, sem conversão de tipo (simplesmente retornando false se os tipos forem diferentes); e `Object.is` irá se comportar da mesma forma que três iguais, mas com tratamento especial para `NaN` e `-0` e `+0` de modo que os dois últimos não são referidos como sendo o mesmo, enquanto `Object.is(NaN, NaN)` será `true`. (Comparando `NaN` com `NaN` ordinariamente - ou seja, usando tanto iguais duplo ou iguais triplo - avalia como `false`, porque IEEE 754 diz isso.) Note que a distinção entre todos eles têm a ver com seu manuseio dos primitivos; nenhum deles compara se os parâmetros são conceitualmente semelhante em estrutura. Para qualquer objetos não-primitivo x e y que têm a mesma estrutura, mas são objetos distintos entre si, todas as formas acima será avaliada como falsa.

Igualdade estrita usando `===`
------------------------------

Igualdade estrita compara dois valores para a igualdade. Nenhum valor é convertido implicitamente para algum outro valor antes de serem comparados. Se os valores tem tipos diferentes, os valores são considerados não-iguais. Caso contrário, se os valores têm o mesmo tipo e não são números, eles são considerados iguais, se tiverem o mesmo valor. Finalmente, se ambos os valores são números, eles são considerados iguais se ambos não são `NaN` e são do mesmo valor, ou se um é `+0` e outro é `-0`.

```js
var num = 0;
var obj = new String("0");
var str = "0";

console.log(num === num); // true
console.log(obj === obj); // true
console.log(str === str); // true

console.log(num === obj); // false
console.log(num === str); // false
console.log(obj === str); // false
console.log(null === undefined); // false
console.log(obj === null); // false
console.log(obj === undefined); // false
```

Igualdade estrita é quase sempre a operação de comparação correta a se usar. Para todos os valores, exceto os números, ele usa a semântica óbvia: um valor é apenas igual a ele mesmo. Para os números que ele usa uma semântica ligeiramente diferente para encobrir dois casos extremamente diferentes. A primeira é que o zero de ponto flutuante é positiva ou negativamente assinada. Isso é útil em representar certas soluções matemáticas, mas como a maioria das situações não se preocupam com a diferença entre `+0` e `-0`, igualdade estrita trata-os como o mesmo valor. A segunda é que ponto flutuante inclui o conceito de um valor não-numérico, `NaN`, para representar a solução para certos problemas matemáticos mal definidos: infinito negativo adicionado ao infinito positivo, por exemplo. Igualdade estrita trata `NaN` como desigual a qualquer outro valor - incluindo o próprio. (O único caso em que `(x! == X)` é `true` é quando `x` é `NaN`.)

Igualdade ampla usando ==
-------------------------

Igualdade ampla compara dois valores para a igualdade, *após* converter ambos os valores para um tipo comum. Após as conversões (um ou ambos os lados podem sofrer conversões), a comparação de igualdade final é realizada exatamente como `===` executa. Igualdade ampla é *simétrica*: `A == B` sempre tem semântica idêntica à `B == A` para quaisquer valores de `A` e `B`.

A comparação de igualdade é realizado da seguinte forma para os operandos dos vários tipos:

|  | `Operand B` |
| --- | --- |
|  |  | Undefined | Null | Number | String | Boolean | Object |
| Operand A | Undefined | `true` | `true` | `false` | `false` | `false` | `IsFalsy(B)` |
| Null | `true` | `true` | `false` | `false` | `false` | `IsFalsy(B)` |
| Number | `false` | `false` | `A === B` | `A === ToNumber(B)` | `ToNumber(B) === A` | `ToPrimitive(B) == A` |
| String | `false` | `false` | `B === ToNumber(A)` | `A === B` | `ToNumber(A) === ToNumber(B)` | `ToPrimitive(B) == A` |
| Boolean | `false` | `false` | `ToNumber(A) === B` | `ToNumber(A) === ToNumber(B)` | `A === B` | `false` |
| Object | `IsFalsy(A)` | `IsFalsy(A)` | `ToPrimitive(A) == B` | `ToPrimitive(A) == B` | `false` | `A === B` |

Na tabela acima, `ToNumber(A)` tenta converter seu argumento para um número antes de comparação. Seu comportamento é equivalente a `+A` (o operador + unário). `ToPrimitive(A)` tenta converter seu argumento de objeto para um valor primitivo, tentando invocar sequências diferentes de `A.toString` e `A.valueOf` métodos em `A`.

Tradicionalmente, e de acordo com ECMAScript, todos os objetos são amplamente desiguais a `undefined` e `null`. Mas a maioria dos navegadores permitem uma classe muito limitada de objetos (especificamente, o objeto `document.all` para qualquer página), em alguns contextos, para agir como se eles *emulassem* o valor `undefined`. Igualdade ampla é um desses contexto. Portanto, o método `IsFalsy(A)` é avaliada como verdadeira se, e somente se, A for um objeto que *emula* `undefined`. Em todos os outros casos, um objeto não é amplamente igual a `undefined` ou `null`.

```js
var num = 0;
var obj = new String("0");
var str = "0";

console.log(num == num); // true
console.log(obj == obj); // true
console.log(str == str); // true

console.log(num == obj); // true
console.log(num == str); // true
console.log(obj == str); // true
console.log(null == undefined); // true

// both false, except in rare cases
console.log(obj == null);
console.log(obj == undefined);
```

Alguns desenvolvedores consideram que nunca é uma boa idéia, praticamente, usar a igualdade ampla. O resultado de uma comparação usando a igualdade estrita é mais fácil de prever, e como nenhum tipo de coerção ocorre, a avaliação pode ser mais rápida.

Igualdade de mesmo valor
------------------------

Igualdade de mesmo valor aborda um caso de uso final: determinar se dois valores são *funcionalmente idêntico* em todos os contextos. (Este caso de uso demonstra uma instância de Liskove substitution principle. Princípio de substituição de Liskove.) Uma instância ocorre quando é feita uma tentativa de transformar uma propriedade imutável:

```js
// Add an immutable NEGATIVE\_ZERO property to the Number constructor.
Object.defineProperty(Number, "NEGATIVE\_ZERO", {
  value: -0,
  writable: false,
  configurable: false,
  enumerable: false,
});

function attemptMutation(v) {
  Object.defineProperty(Number, "NEGATIVE\_ZERO", { value: v });
}
```

`Object.defineProperty` irá disparar uma exceção ao tentar alterar uma propriedade imutável que realmente iria alterá-lo, mas ele não faz nada se nenhuma mudança real for solicitada. Se `v` for `-0`, nenhuma mudança foi solicitada, e nenhum erro será disparado. Mas se `v` for `+0`, `Number.NEGATIVE_ZERO` não teria mais o seu valor imutável. Internamente, quando uma propriedade imutável é redefinida, o valor recém-especificado é comparado com o valor atual usando a igualdade de mesmo valor.

Igualdade de mesmo valor é fornecida pelo método `Object.is.`

Igualdade abstrata, igualdade estrita, e de mesmo valor na especificação
------------------------------------------------------------------------

No ES5, a comparação efetuada por `==` é descrita em Seção 11.9.3, O Algoritmo da Igualdade Abstrata. A comparação `===` está em 11.9.6, O Algoritmo de Igualdade Estrita. (Veja estes. Eles são breve e legível. Dica: leia o algoritmo de igualdade estrita primeiro.) ES5 também descreve, em Seção 9.12, o Algoritmo de Mesmo Valor para uso internamente pelo motor de JS. É em grande parte o mesmo que o Algoritmo de Igualdade Estrita, exceto que 11.9.6.4 e 9.12.4 diferem em manipulação do `Number`. ES6 simplesmente se propõe a expor este algoritmo através de `Object.is`.

Podemos ver que com iguais duplos e triplos, com exceção de fazer uma verificação de tipo inicial 11.9.6.1, o Algoritmo de Igualdade Estrita é um subconjunto do Algoritmo Igualdade Abstrata, porque 11.9.6.2-7 correspondem a 11.9.3.1.a -f.

Um modelo para a compreensão comparações de igualdade?
------------------------------------------------------

Antes do ES6, você poderia dizer, de iguais duplos e iguais triplos, que um é uma versão "melhorada" do outro. Por exemplo, alguém poderia dizer que dois iguais é uma versão estendida de três iguais, porque o anterior faz tudo o que este último faz, mas com conversão de tipo nos seus operandos. Por exemplo, 6 == "6". (Alternativamente, alguém poderia dizer que dois iguais é a linha de base, e três iguais são uma versão melhorada, porque requer dois operandos para ser do mesmo tipo, por isso adiciona uma restrição extra. Qual deles é o melhor modelo para compreensão depende como você optar por ver as coisas.)

No entanto, esta forma de pensar sobre os operadores de igualdade embutida não é um modelo que pode ser esticado para permitir um lugar para Object.is de ES6 neste "espectro". Object.is não é simplesmente "mais frouxo" que dois iguais ou "mais rigorosa" do que três iguais, nem se encaixa em algum lugar entre eles (ex: sendo tanto mais rigorosas que dois iguais, mas mais flexível do que três iguais). Podemos ver a partir da tabela de comparações de igualdade abaixo que isto é devido à forma que Object.is manipula NaN. Observe que, se Object.is(NaN, NaN) avalia como false, nós *poderiamos* dizer que ele se encaixa no espectro amplo/estrito como um forma ainda mais rigorosa das três iguais, um que distingue entre -0 e +0. A manipulação do NaN significa que este é não-verdadeiro, entretanto. Infelizmente, Object.is simplesmente tem que ser pensado em termos de suas características específicas, ao invés de sua amplitude ou rigorosidade no que diz respeito aos operadores de igualdade.

| x | y | == | === | Object.is |
| --- | --- | --- | --- | --- |
| `undefined` | `undefined` | `true` | `true` | `true` |
| `null` | `null` | `true` | `true` | `true` |
| `true` | `true` | `true` | `true` | `true` |
| `false` | `false` | `true` | `true` | `true` |
| `"foo"` | `"foo"` | `true` | `true` | `true` |
| `{ foo: "bar" }` | `x` | `true` | `true` | `true` |
| `0` | `0` | `true` | `true` | `true` |
| `+0` | `-0` | `true` | `true` | `false` |
| `0` | `false` | `true` | `false` | `false` |
| `""` | `false` | `true` | `false` | `false` |
| `""` | `0` | `true` | `false` | `false` |
| `"0"` | `0` | `true` | `false` | `false` |
| `"17"` | `17` | `true` | `false` | `false` |
| `[1,2]` | `"1,2"` | `true` | `false` | `false` |
| `new String("foo")` | `"foo"` | `true` | `false` | `false` |
| `null` | `undefined` | `true` | `false` | `false` |
| `null` | `false` | `false` | `false` | `false` |
| `undefined` | `false` | `false` | `false` | `false` |
| `{ foo: "bar" }` | `{ foo: "bar" }` | `false` | `false` | `false` |
| `new String("foo")` | `new String("foo")` | `false` | `false` | `false` |
| `0` | `null` | `false` | `false` | `false` |
| `0` | `NaN` | `false` | `false` | `false` |
| `"foo"` | `NaN` | `false` | `false` | `false` |
| `NaN` | `NaN` | `false` | `false` | `true` |

Quando usar `Object.is` ao invés de três iguais
-----------------------------------------------

Além da forma como trata `NaN`, geralmente, a única vez que o comportamento especial do Object.is em direção a zeros é provável que seja interessante é na busca de determinados regimes de meta-programação, especialmente em relação a descritores de propriedade quando é desejável para o seu trabalho para espelhar algumas das características de Object.defineProperty. Se o seu caso de uso não exige isso, sugere-se a evitar Object.is e usar === (en-US) em vez disso. Mesmo se suas exigências envolvem comparações entre dois valores NaN avaliarem para true, geralmente é mais fácil para caso especial o NaN checar (usando o isNaN método disponível a partir de versões anteriores do ECMAScript) do que descobrir como cálculos circundantes podem afetar o sinal de todos os zeros que você encontra em sua comparação.

Aqui está uma lista exaustiva de métodos e operadores integrados que pode causar uma distinção entre -0 e +0 a manifestar-se em seu código:

`- (negação unário)` (en-US)

É óbvio que negando 0 produz -0. Mas a abstração de uma expressão pode causar -0 a fluência em quanto você não percebe isso. Por exemplo, considere:

```js
let stoppingForce = obj.mass \* -obj.velocity;
```

If obj.velocity is 0 (ou calcula para 0), um -0 é introduzido naquele lugar e propaga-se em stoppingForce.

`Math.atan2`

`Math.ceil`

`Math.pow`

`Math.round`

É possível que um -0 para ser introduzido em uma expressão como um valor de retorno desses métodos, em alguns casos, mesmo quando nenhum -0 exista como um dos parâmetros. Por exemplo, usando Math.pow para levantar -Infinity a potência de qualquer número, expoente ímpar negativo avaliada como -0. Consulte a documentação para os métodos individuais.

`Math.floor`

`Math.max`

`Math.min`

`Math.sin`

`Math.sqrt`

`Math.tan`

É possível obter um -0 valor de retorno para fora destes métodos em alguns casos em que um -0 existe como um dos parâmetros. Por exemplo, `Math.min(-0, +0)` resulte em -0. Consulte a documentação para os métodos individuais.

~ (en-US)

<< (en-US)

>> (en-US)

Cada um destes operadores usa o algoritmo ToInt32 internamente. Uma vez que existe apenas uma representação para 0 no tipo integer de 32 bits interno, -0 não vai sobreviver a uma ida e volta após uma operação inversa. Por exemplo, tanto `Object.is(~~(-0), -0)` e `Object.is(-0 << 2 >> 2, -0)` avaliar como `false`.

Baseando-se em `Object.is` quando a sinalização de zeros não é levado em conta podem ser perigosos. Claro que, quando a intenção é fazer a distinção entre `-0` e `+0`, isso faz exatamente o que é desejado.

Veja também
-----------

* Tabela de Comparação JS


Guia JavaScript - JavaScript

Guia JavaScript
===============

O Guia JavaScript mostra como usar JavaScript e dá uma visão geral da linguagem. Se você quer começar com JavaScript ou programação em geral, consulte os artigos na área de aprendizagem. Se você precisar de informações mais aprofundadas sobre algum recurso da linguagem, consulte a referência JavaScript.

Capítulos
---------

Este guia está dividido em vários capítulos:

* Introdução
Sobre este guia
Sobre JavaScript
JavaScript e Java
ECMAScript
Ferramentas
Olá Mundo
* Sintaxe e tipos
Sintaxe básica e comentários
Declarações
Escopo de variável
Hoisting
Estruturas de dados e Tipos
Literais
* Controle de fluxo e manipulação de erro
`if...else`
`switch`
`try`/`catch`/`throw`
Objetos de erro
Promises
* Laços e iteração
`for while do...while break/continue for..in for..of`
* Funções
Definição de funções
Chamando funções
Escopo da função
Closures
Argumentos & parâmetros
Funções de seta
* Expressões e operadores
Atribuição & comparações
Operadores aritméticos
Operadores lógicos & bit a bit
Operador condicional (Ternário)
* Números e datas
Números
Objeto de números
Objeto Math
Objeto Data
* Formatação de texto
Strings
Objetos de strings
Modelos de strings
Internacionalização
* Expressões Regular
Criando uma expressão regular
Padrão de escrita de uma expressão regular
Trabalhando com expressões regular
* Coleções Indexadas
Arrays
Arrays digitados
* Coleções Chaveadas
Maps
WeakMaps
Set
WeakSet
* Trabalhando com objetos
Objetos e propriedades
Criando Objetos
Definindo Métodos
Getter e setter
* Detalhes do modelo de objetos
POO baseada na prototipagem
Criando hierarquias de objetos
Herança
* Iteradores e geradores
Iterators
Iterables
Generators
* Meta programação
`Proxy`
Handlers e traps
Proxy revogável
`Refletor`
* Next »


Visão geral das tecnologias JavaScript - JavaScript

Visão geral das tecnologias JavaScript
======================================

Enquanto o HTML é usado para armazenar o conteúdo e a formatação de uma página web e o CSS define a formatação e a aparência, o JavaScript é usado para adicionar interatividade a uma página web e criar aplicações web ricas.

No entanto, o termo genérico "JavaScript" tal como é entendido no contexto do navegador contém vários elementos bem diferentes. Um deles é a linguagem principal (ECMAScript), outra é a coleção das Web APIs (en-US), incluindo o DOM (Document Object Model).

JavaScript, a linguagem principal (ECMAScript)
----------------------------------------------

O núcleo da linguagem JavaScript é padronizado pelo comitê ECMA TC39 como uma linguagem chamada ECMAScript (en-US). A última versão da especificação é ECMAScript 5.1.

Este núcleo da linguagem é também usado em ambientes fora do navegador, por exemplo em node.js.

### O que se enquadra no escopo ECMAScript?

Entre outras coisas, o ECMAScript define:

* A sintaxe da linguagem (regras de análise, palavras-chave, controle de fluxo, inicialização de objetos literais...)
* Mecanismos para manuseio de erros (`throw`, `try...catch`, habilidade para criar tipos de `Error` definido pelo usuário)
* Tipos (*boolean*, *number*, *string*, *function*, *object*...)
* O objeto global. Num navegador esse objeto global é o objeto *window*, mas o ECMAScript apenas define as APIs, não especificamente para navegadores, por exemplo: *parseInt*, *parseFloat*, *decodeURI*, *encodeURI*...
* Um mecanismo de herança baseado em protótipo
* Objetos e funções embutidas (`JSON`, `Math`, Array, *Object introspection*...)
* Modo estrito (rigoroso)
### Suporte do navegador

Desde Agosto de 2014, as atuais versões dos principais navegadores implementaram o ECMAScript 5.1 e o ECMAScript 2015, mas versões mais antigas continuam usando a implementação do ECMAScript 3 e apenas partes do ECMAScript 5. Navegadores mais modernos já implementaram grande parte do ECMAScript 6.

### Futuro

A 6ª edição principal do ECMAScript foi oficialmente aprovada e publicada como norma em 17 de junho de 2015 pela Assembléia Geral da ECMA. Desde então, as Edições ECMAScript são publicadas anualmente.

### API de Internacionalização

A API de Especificação de Internacionalização do ECMASCRIPT é uma adição para a Especificação de Linguagem ECMAScript, também padronizada pela Ecma TC39. A API de internacionalização fornece intercalação (comparação de string), formatação numérica, formatação de data e tempo para aplicações JavaScript, permitindo que aplicativos escolham o idioma e adaptem a funcionalidade às suas necessidades. O padrão foi aprovado em dezembro de 2012; O status das implementações nos navegadores é rastreado na documentação do objeto Intl. A especificação de Internacionalização hoje em dia também é ratificada anualmente e os navegadores aprimoram as suas implementações constantemente.

As APIs Web e o DOM
-------------------

### WebIDL

A Especificação da WebIDL provê a junção entre as tecnologias DOM e o ECMAScript.

### O núcleo do DOM

O Document Object Model (DOM) é uma **convenção multiplataforma** e **lndependente de linguagem** para representação e interação com objetos em documentos HTML, XHTML, e XML. Objetos no **DOM tree** (árvore do DOM) podem ser adereçados e manipulados utilizando métodos em objetos. A W3C padroniza o Core Document Object Model (Núcleo do Documento do Modelo de Objeto), o qual define interfaces de agnóstico de linguagem que abstraem documentos HTML e XML como objetos, e também define mecanismos para manipular essa abstração. Entre as definições do DOM, podemos encontrar:

* A estrutura do documento, um tree model (modelo de árvore), e a arquitetura do DOM Event (Evento do DOM) no DOM core (núceo do DOM): `Node`, `Element`, `DocumentFragment`, `Document`, `DOMImplementation` (en-US), `Event`, `EventTarget`, …
* Uma definição menos rigorosa do DOM Event Architecture, assim como eventos específicos no DOM events.
* Outras coisas como o DOM Traversal e o DOM Range.

Pela perspectiva do EXMScript, objetos definidos na especificação do DOM são chamados de "host objects".

### HTML DOM

HTML, a linguagem de marcação da Web, é especificada nos termos do DOM. Situado além dos conceitos de abstração definidos no DOM Core, o HTML também define o *significado* dos elementos. O HTML DOM inclui coisas como a propriedade `className` em elementos HTML, ou APIs como `document.body`.

A especificação HTML também define restrições nos objetos; por exemplo, ela requer que todos os filhos de um elemento `ul`, que representam uma lista desordenada, sejam elementos `li`, que representem itens de lista. Em linhas gerais, ele também proíbe o uso de elementos e atributos que não estão definidos em um padrão.

Procurando pelo `Document` object, `Window` object, e outros elementos DOM? Leia a Documentação do DOM.

Outras APIs de destaque
-----------------------

* As funções `setTimeout` (en-US) e `setInterval` foram inicialmente especificadas na interface `Window` no Padrão HTML.
* XMLHttpRequest. Possibilita enviar requisições HTTP assíncronas.
* A Fetch API fornece uma abstração mais ergonômica para requisições de rede.
* CSS Object Model. O CSSOM é utilizado para abstrair regras CSS como objetos
* WebWorkers. API que permite computação paralela.
* WebSockets. API que permite comunicação bi-direcional de baixo-nível.
* Canvas 2D Context. API de ilustração (desenho) para o elemento canvas.
* A interface WebAssembly fornece utilitários para comunicação entre código JavaScript e módulos WebAssembly.

Ambientes sem navegador (como Node.js) geralmente não têm APIs DOM — porque não interagem com um documento — mas ainda assim implementam muitas APIs da Web, como `fetch()` e `setTimeout()` (en-US).

### Suporte de Navegadores

Todo desenvolvedor já percebeu que o DOM é uma bagunça. A uniformidade no suporte dos Navegadores varia muito de feature para feature. A principal razão para essa situação é o fato de que muitas features importantes do DOM possuem (quando possuem) especificações não muito claras. Além disso, diferentes Navegadores adicionaram features incompatíveis para a sobreposição de casos de uso (como o event model do Internet Explorer). A atual (Junho de 2011) tendência é que a W3C e particularmente a WHATWG estão definindo features mais antigas em detalhes, a fim de melhorar a interoperabilidade. Seguindo esta tendência, Navegadores estão melhorando suas implementações baseados nessas especificações.

Uma abordagem comum, porém não a mais confiável, para compatibilidade cross-browser é utilizar a biblioteca JavaScript. Essas bibliotecas abstrem as features do DOM e garantem que suas API's funcionem de forma similar nos navegadores. Alguns dos frameworks mais utilizados são o jQuery, o prototype, e o YUI.