Coleções chaveadas - JavaScript

Coleções chaveadas
==================

* « Previous
* Next »

Este capítulo apresenta coleções de dados que são ordenados por uma chave; Objetos Map e Set contêm elementos que são iteráveis em ordem de inserção.

Mapas
-----

### `Objeto Map`

ECMAScript 6 apresenta uma nova estrutura de dados para mapear valores para valores. Um objeto `Map` é um simples mapa de chave/valor que pode ter seus elementos iterados por ordem de inserção.

O código a seguir mostra algumas operações básicas com um `Map`. Veja também a página de referência do `Map` para mais exemplos e a API completa. Você pode usar um laço `for...of` para retornar um array de `[chave, valor]` para cada iteração.

```js
var sayings = new Map();
sayings.set("dog", "woof");
sayings.set("cat", "meow");
sayings.set("elephant", "toot");
sayings.size; // 3
sayings.get("fox"); // undefined
sayings.has("bird"); // false
sayings.delete("dog");
sayings.has("dog"); // false

for (var [key, value] of sayings) {
  console.log(key + " goes " + value);
}
// "cat goes meow"
// "elephant goes toot"

sayings.clear();
sayings.size; // 0
```

### `Object` e `Map` comparados

Tradicionalmente, objetos tem sido usado para mapear strings para valores. Objetos permitem que você defina chaves para valores, recupere esses valores, exclua chaves e detecte se algo está armazenado em uma chave. Objetos `Map`, contudo, possuem algumas vantagens que os tornam mapas melhores.

* As chaves de um `Objeto` são `Strings`, onde elas podem ser de qualquer valor para um `Map`.
* Você pode obter o tamanho de um `Map` facilmente enquanto que para um `Object`, você tem que obter manualmente o seu tamanho.
* A iteração de mapas é por ordem de inserção dos elementos.
* Um `Object` tem um protótipo, então existem chaves padrão no mapa. (este pode ser ignorado usando `map = Object.create(null)`).

Estes dois tipos podem ajudar você a decidir se usa um `Map` ou um `Object`:

* Use mapas sobre objetos quando as chaves forem desconhecidas até a execução, e quando todas as chaves são do mesmo tipo e todos valores são do mesmo tipo.
* Use mapas caso haja a necessidade de armazenar valores primitivos como chaves, porque objetos tratam cada chave como uma string ou um valor numérico, valor booleano ou qualquer outro valor primitivo.
* Use objetos quando há uma lógica que opera em elementos individuais.
### `Objeto WeakMap`

O objeto `WeakMap` é uma coleção de pares de chave/valor em que as **chaves são somente objetos** e seus valores podem ser valores arbitrários. As referências do objeto nas chaves são *fracamente* mantidas, isso significa que eles são alvo da garbage collection (coleta de lixo) se não houver nenhuma outra referência para o objeto. A API `WeakMap` é a mesma API do `Map`.

Uma diferença para objetos `Map` é que chaves `WeakMap` não são enumeráveis (isto é, não há um método que dê a você uma lista de chaves). Se eles fossem, a lista dependeria do estado da coleta de lixo, introduzindo um não-determinismo.

Para mais informações e código de exemplo, veja também "Por quê WeakMap?" na página de referência `WeakMap`.

Um caso de uso de objetos `WeakMap` é armazenar dados privados para um objeto ou ocultar detalhes de implementação. O exemplo a seguir é Nick Fitzgerald a partir de um post "Ocultando detalhes de implementação com WeakMaps ECMAScript 6" em seu blog. Os dados privados e métodos pertencem ao objeto e são armazenados nos objetos WeakMap `privados`. Tudo exposto na instância e o protótipo é público, todo o restante é inacessível a partir do mundo externo por que `privado` não é exportado pelo módulo.

```js
const privates = new WeakMap();

function Public() {
  const me = {
    // Dados privados vem aqui
  };
  privates.set(this, me);
}

Public.prototype.method = function () {
  const me = privates.get(this);
  // Faça coisas com dado privado em `me`...
};

module.exports = Public;
```

Conjuntos
---------

### `Objeto Set`

Objetos `Set` são coleções de valores. Você pode iterar seus elementos em ordem de inserção. Um valor em um `Set` só pode ocorrer uma vez; ele é único em uma coleção `Set`.

O código a seguir mostra algumas operações básicas com um `Set`. Veja também a página de referência `Set` para mais exemplos e a API completa.

```js
var mySet = new Set();
mySet.add(1);
mySet.add("some text");
mySet.add("foo");

mySet.has(1); // true
mySet.delete("foo");
mySet.size; // 2

for (let item of mySet) console.log(item);
// 1
// "some text"
```

### Conversão entre Array e Set

Você pode criar um `Array` a partir de um Set usando `Array.from` ou o operador de propagação (en-US). Além disso, o construtor `Set` aceita um `Array` para converter em outra direção. Observe novamente que objetos `Set` armazenam valores únicos, então quaisquer elementos duplicados de um Array são excluídos quando convertidos.

```js
Array.from(mySet);
[...mySet2];

mySet2 = new Set([1, 2, 3, 4]);
```

### `Array` e `Set` comparados

Tradicionalmente, um conjunto de elementos tem sido armazenados em arrays JavaScript em muitas situações. O novo objeto `Set`, contudo, tem algumas vantagens:

* Checar se um elemento existe em uma coleção usando `indexOf` para arrays é lento.
* Objetos `Set` permitem que você exclua elementos por seu valor. Com um array você teria que unir baseado no índice do elemento.
* O valor `NaN` não pode ser encontrado com `indexOf` no array.
* Objetos `Set` armazenam valores únicos, você não tem que manter o controle de duplicidades manualmente por você mesmo.
### `Objeto WeakSet`

Objetos `WeakSet` são coleções de objetos. Um objeto no `WeakSet` só pode ocorrer uma vez; Isto é único em coleções `WeakSet` e objetos não são enumeráveis.

As principais diferenças para objetos `Set` são:

* Em contraste com `Sets`, `WeakSets` são **apenas coleções de objetos** e não de valores arbritários de qualquer tipo.
* O `WeakSet` é *fraco*: Referências para objetos são fracamente realizadas na coleção. Se não há outra referência para um objeto armazenado no `WeakSet`, eles podem ser coletados pelo coletor de lixo. Isso significa também que não há uma lista de objetos correntes armazenados na coleção. `WeakSets` não são enumeráveis.

Os casos de uso do objeto `WeakSet` são limitados. Eles não vão desperdiçar memória para ser seguro o uso de elementos DOM como chaves e marcá-los para propósitos de controle, por exemplo.

Igualdade de chave e valor do `Map` and `Set`
---------------------------------------------

Ambos, a igualdade de chaves de objetos `Map` e a igualdade de valor de objetos `Set`, são baseados no "algoritmo mesmo valor de zero":

* Igualdade funciona como o operador de comparação de identidade `===`.
* `-0` e `+0` são considerados iguais.
* `NaN` é considerado igual a ela mesmo (contrário de `===`).
* « Previous
* Next »


Expressões e operadores - JavaScript

Expressões e operadores
=======================

* « Previous
* Next »

Este artigo descreve expressões e operadores de JavaScript, incluindo operadores de atribuição, comparação, aritméticos, bit a bit, lógicos, de strings e especiais.

Operadores
----------

O JavaScript possui os tipos de operadores a seguir. Esta seção descreve os operadores e contém informações sobre precedência de operadores.

* Operadores de atribuição
* Operadores de comparação
* Operadores aritméticos
* Operadores bit a bit
* Operadores lógicos
* Operadores de string
* Operador condicional (ternário)
* Operador vírgula
* Operadores unário
* Operadores relacionais

O JavaScript possui tanto operadores *binários* quanto *unários* e um operador ternário, o operador condicional. Um operador binário exige dois operandos, um antes do operador e outro depois:
```

operando1 operador operando2
```

Por exemplo, `3+4` ou `x*y`.

Um operador unário exige um único operando, seja antes ou depois do operador:
```

operador operando
```

ou
```

operando operador
```

Por exemplo, `x++` ou `++x`.

### Operadores de atribuição

Um operador de atribuição atribui um valor ao operando à sua esquerda baseado no valor do operando à direita. O operador de atribuição básico é o igual (=), que atribui o valor do operando à direita ao operando à esquerda. Isto é, x = y atribui o valor de y a x.

Os outros operadores de atribuição são encurtamentos de operadores padrão, como mostrado na tabela a seguir.

| Nome | Operador encurtado | Significado |
| --- | --- | --- |
| Atribuição | x = y | x = y |
| Atribuição de adição | `x += y` | `x = x + y` |
| Atribuição de subtração | `x -= y` | `x = x - y` |
| Atribuição de multiplicação | `x *= y` | `x = x * y` |
| Atribuição de divisão | `x /= y` | `x = x / y` |
| Atribuição de resto | `x %= y` | `x = x % y` |
| Atribuição exponencial | x \*\*= y | x = x \*\* y |
| Atribuição bit-a-bit por deslocamento á esquerda | `x <<= y` | `x = x << y` |
| Atribuição bit-a-bit por deslocamento á direita | `x >>= y` | `x = x >> y` |
| Atribuiçãode bit-a-bit deslocamento á direita não assinado | `x >>>= y` | `x = x >>> y` |
| Atribuição AND bit-a-bit | `x &= y` | `x = x & y` |
| Atribuição XOR bit-a-bit | `x ^= y` | `x = x ^ y` |
| Atribuição OR bit-a-bit | `x |= y` | `x = x | y` |

### Operadores de comparação

Um operador de comparação compara seus operandos e retorna um valor lógico baseado em se a comparação é verdadeira. Os operandos podem ser numéricos, strings, lógicos ou objetos. Strings são comparadas com base em ordenação lexográfica utilizando valores Unicode. Na maioria dos casos, se dois operandos não são do mesmo tipo, o JavaScript tenta convertê-los para um tipo apropriado. Isto geralmente resulta na realização de uma comparação numérica. As únicas exceções a esta regra são os operadores `===` e o `!==`, que realizam comparações de igualdade e desigualdade "estritas". Estes operadores não tentam converter os operandos em tipos compatíveis antes de verificar a igualdade. A tabela a seguir descreve os operadores de comparação levando em conta o seguinte código:

```js
var var1 = 3;
var var2 = 4;
```

| Operador | Descrição | Exemplos que retornam verdadeiro |
| --- | --- | --- |
| Igual (`==`) | Retorna verdadeiro caso os operandos sejam iguais. | `3 == var1` `"3" == var1` `3 == '3'` |
| Não igual (`!=`) | Retorna verdadeiro caso os operandos não sejam iguais. | `var1 != 4 var2 != "3"` |
| Estritamente igual (`===`) | Retorna verdadeiro caso os operandos sejam iguais e do mesmo tipo. Veja também `Object.is` e igualdade em JS (en-US). | `3 === var1` |
| Estritamente não igual (`!==`) | Retorna verdadeiro caso os operandos não sejam iguais e/ou não sejam do mesmo tipo. | `var1 !== "3" 3 !== '3'` |
| Maior que (`>`) | Retorna verdadeiro caso o operando da esquerda seja maior que o da direita. | `var2 > var1 "12" > 2` |
| Maior que ou igual (`>=`) | Retorna verdadeiro caso o operando da esquerda seja maior ou igual ao da direita. | `var2 >= var1 var1 >= 3` |
| Menor que (`<`) | Retorna verdadeiro caso o operando da esquerda seja menor que o da direita. | `var1 < var2 "12" < "2"` |
| Menor que ou igual (`<=`) | Retorna verdadeiro caso o operando da esquerda seja menor ou igual ao da direita. | `var1 <= var2 var2 <= 5` |

**Nota:** (**=>**) não é um operador, mas a notação para função de seta

### Operadores aritméticos

Operadores aritméticos tomam valores numéricos (sejam literais ou variáveis) como seus operandos e retornam um único valor númerico. Os operadores aritméticos padrão são os de soma (`+`), subtração (`-`), multiplicação (`*`) e divisão (`/`). Estes operadores trabalham da mesma forma como na maioria das linguagens de programação quando utilizados com números de ponto flutuante (em particular, repare que divisão por zero produz um `NaN` (en-US)). Por exemplo:

```js
console.log(1 / 2); /\* imprime 0.5 \*/
console.log(1 / 2 == 1.0 / 2.0); /\* isto também é verdadeiro \*/
```

Em complemento às operações aritméticas padrões (+, -, \* /), o JavaScript disponibiliza os operadores aritméticos listados na tabela a seguir.

| Operador | Descrição | Exemplo |
| --- | --- | --- |
| Módulo (%) | Operador binário. Retorna o inteiro restante da divisão dos dois operandos. | 12 % 5 retorna 2. |
| Incremento (++) | Operador unário. Adiciona um ao seu operando. Se usado como operador prefixado (`++x`), retorna o valor de seu operando após a adição. Se usado como operador pósfixado (`x++`), retorna o valor de seu operando antes da adição. | Se `x` é 3, então `++x` define `x` como 4 e retorna 4, enquanto `x++` retorna 3 e, somente então, define `x` como 4. |
| Decremento (--) | Operador unário. Subtrai um de seu operando. O valor de retorno é análogo àquele do operador de incremento. | Se `x` é 3, então `--x` define `x` como 2 e retorna 2, enquanto `x--` retorna 3 e, somente então, define `x` como 2. |
| Negação (-) | Operador unário. Retorna a negação de seu operando. | Se `x` é 3, então `-x` retorna -3. |
| Adição (+) | Operador unário. Tenta converter o operando em um número, sempre que possível. | +"3" retorna 3.+true retorna 1. |
| Operador de exponenciação (\*\*)
Experimental
 | Calcula a base elevada á potência do expoente, que é, base`expoente` | 2 \*\* 3 retorna 8.10 \*\* -1 retorna 0.1 |

### Operadores bit a bit

Operadores bit a bit tratam seus operandos como um conjunto de 32 bits (zeros e uns), em vez de tratá-los como números decimais, hexadecimais ou octais. Por exemplo, o número decimal nove possui uma representação binária 1001. Operadores bit a bit realizam suas operações nestas representações, mas retornam valores numéricos padrões do JavaScript.

A tabela a seguir resume os operadores bit a bit do JavaScript.

| Operador | Expressão | Descrição |
| --- | --- | --- |
| AND | `a & b` | Retorna um 1 para cada posição em que os bits da posição correspondente de ambos operandos sejam uns. |
| OR | `a | b` | Retorna um 0 para cada posição em que os bits da posição correspondente de ambos os operandos sejam zeros. |
| XOR | `a ^ b` | Retorna um 0 para cada posição em que os bits da posição correspondente são os mesmos. [Retorna um 1 para cada posição em que os bits da posição correspondente sejam diferentes.] |
| NOT | `~ a` | Inverte os bits do operando. |
| Deslocamento à esquerda | `a << b` | Desloca `a` em representação binária `b` bits à esquerda, preenchendo com zeros à direita. |
| Deslocamento à direita com propagação de sinal | `a >> b` | Desloca `a` em representação binária `b` bits à direita, descartando bits excedentes. |
| Deslocamento à direita com preenchimento zero | `a >>> b` | Desloca `a` em representação binária `b` bits à direita, descartando bits excedentes e preenchendo com zeros à esquerda. |

#### Operadores bit a bit lógicos

Conceitualmente, os operadores bit a bit lógicos funcionam da seguinte maneira:

* Os operandos são convertidos em inteiros de 32 bits e expressos como uma série de bits (zeros e uns). Números com representação maior que 32 bits terão seus bits truncados. Por exemplo, o seguinte inteiro tem representação binária maior que 32 bits será convertido em um inteiro de 32 bits.
```

Antes: 11100110111110100000000000000110000000000001
Depois:            10100000000000000110000000000001
```

* Cada bit do primeiro operando é pareado com o bit correspondente do segundo operando: primeiro bit com primeiro bit, segundo bit com segundo bit e assim por diante.
* O operador é aplicado a cada par de bits e o resultado é construído bit a bit.

Por exemplo, a representação binária de nove é 1001 e a representação binária de quinze é 1111. Desta forma, quando operadores bit a bit são aplicados a estes valores, os resultados são como se segue:

| Expressão | Resultado | Descrição binária |
| --- | --- | --- |
| `15 & 9` | `9` | `1111 & 1001 = 1001` |
| `15 | 9` | `15` | `1111 | 1001 = 1111` |
| `15 ^ 9` | `6` | `1111 ^ 1001 = 0110` |
| `~15` | `-16` | `~ 0000 0000 … 0000 1111 = 1111 1111 … 1111 0000` |
| `~9` | `-10` | `~ 0000 0000 … 0000 1001 = 1111 1111 … 1111 0110` |

**Nota:** No quadro acima perceba que todos os 32 bits são invertidos quando usa-se o operador bit a bit NOT, e que os bits mais significativos (extrema esquerda) são definidos com 1 que representam valores negativos (representação complemento de dois).

#### Operadores de deslocamento bit a bit

Os operadores de deslocamento bit a bit possui dois operandos: o primeiro é uma quantidade a ser deslocada e o segundo especifica o número de posições binárias as quais o primeiro operando deverá ser deslocado. A direção da operação de deslocamento é controlada pelo operador utilizado.

Operadores de deslocamento convertem seus operandos em inteiros de 32 bits e retornam um resultado do tipo do operando à esquerda.

Os operadores de deslocamento são listados na tabela a seguir.

| Operador | Descrição | Exemplo |
| --- | --- | --- |
| `Deslocamento à esquerda (<<)` | Este operador desloca o primeiro operando pelo número especificado de bits à esquerda. Bits excedentes deslocados para fora do limite à esquerda são descartados. Bits zero são inseridos à direita. | `9<<2` produz 36 porque 1001 deslocado 2 bits à esquerda se torna 100100, que é 36. |
| Deslocamento à direita com propagação de sinal (`>>`) | Este operador desloca o primeiro operando pelo número especificado de bits à direita. Bits excedentes deslocados para fora do limite à direita são descartados. Cópias dos bits mais à esquerda são deslocadas a partir da esquerda. | `9>>2` produz 2 porque 1001 deslocado 2 bits à direita se torna 10, que é 2. De forma similar, `-9>>2` produz -3 porque o sinal é preservado. |
| Deslocamento à direita com preenchimento zero (`>>>`) | Este operador desloca o primeiro operando pelo número especificado de bits à direita. Bits excedentes deslocados para fora do limite à direita são descartados. Bits zero são inseridos à esquerda. | `19>>>2` produz 4 porque 10011 deslocado 2 bits à direita se torna 100, que é 4. Para números não negativos o deslocamento à direita com propagação de sinal e o deslocamento à direita com preenchimento zero produzem o mesmo resultado. |

### Operadores lógicos

Operadores lógicos são utilizados tipicamente com valores booleanos (lógicos); neste caso, retornam um valor booleano. Entretanto, os operadores && e || na verdade retornam o valor de um dos operandos especificados, de forma que se esses operadores forem utilizados com valores não-booleanos, eles possam retornar um valor não-booleano. Os operadores lógicos são descritos na seguinte tabela.

| Operador | Utilização | Descrição |
| --- | --- | --- |
| `AND lógico (&&)` | `expr1 && expr2` | (E lógico) - Retorna `expr1` caso possa ser convertido para falso; senão, retorna `expr2`. Assim, quando utilizado com valores booleanos, `&&` retorna verdadeiro caso ambos operandos sejam verdadeiros; caso contrário, retorna falso. |
| `OU lógico (||)` | `expr1 || expr2` | (OU lógico) - Retorna `expr1` caso possa ser convertido para verdadeiro; senão, retorna `expr2`. Assim, quando utilizado com valores booleanos, `||` retorna verdadeiro caso ambos os operandos sejam verdadeiro; se ambos forem falsos, retorna falso. |
| `NOT lógico (!)` | `!expr` | (Negação lógica) Retorna falso caso o único operando possa ser convertido para verdadeiro; senão, retorna verdadeiro. |

Exemplos de expressões que podem ser convertidas para falso são aquelas que são avaliados como nulo, 0, string vazia ("") ou `undefined`.

O código a seguir mostra exemplos do operador && (E lógico).

```js
var a1 = true && true; // t && t retorna true
var a2 = true && false; // t && f retorna false
var a3 = false && true; // f && t retorna false
var a4 = false && 3 == 4; // f && f retorna false
var a5 = "Gato" && "Cão"; // t && t retorna Cão
var a6 = false && "Gato"; // f && t retorna false
var a7 = "Gato" && false; // t && f retorna false
```

O código a seguir mostra exemplos do operador || (OU lógico).

```js
var o1 = true || true; // t || t retorna true
var o2 = false || true; // f || t retorna true
var o3 = true || false; // t || f retorna true
var o4 = false || 3 == 4; // f || f retorna false
var o5 = "Gato" || "Cão"; // t || t retorna Gato
var o6 = false || "Gato"; // f || t retorna Gato
var o7 = "Gato" || false; // t || f retorna Gato
```

O código a seguir mostra exemplos do operador ! (negação lógica).

```js
var n1 = !true; // !t retorna false
var n2 = !false; // !f retorna true
var n3 = !"Gato"; // !t retorna false
```

#### Avaliação de curto-circuito

Como expressões lógicas são avaliadas da esquerda para a direita, elas são testadas como possíveis avaliações de "curto-circuito" utilizando as seguintes regras:

* `false` && *qualquercoisa* é avaliado em curto-circuito como falso.
* `true` || *qualquercoisa* é avaliado em curto-circuito como verdadeiro.

As regras de lógica garantem que estas avaliações estejam sempre corretas. Repare que a parte *qualquercoisa* das expressões acima não é avaliada, de forma que qualquer efeito colateral de fazê-lo não produz efeito algum.

### Operadores de string

Além dos operadores de comparação, que podem ser utilizados em valores string, o operador de concatenação (+) concatena dois valores string, retornando outra string que é a união dos dois operandos.

Por exemplo,
```

 console.log("minha " + "string"); // exibe a string "minha string".
```

O operador de atribuição encurtado += também pode ser utilizado para concatenar strings.

Por exemplo,
```

var minhaString = "alfa";
minhaString += "beto"; // É avaliada como "alfabeto" e atribui este valor a minhastring.
```

### Operador condicional (ternário)

O operador condicional é o único operador JavaScript que utiliza três operandos. O operador pode ter um de dois valores baseados em uma condição. A sintaxe é:
```

condicao ? valor1 : valor2
```

Se `condicao` for verdadeira, o operador terá o valor de `valor1`. Caso contrário, terá o valor de `valor2`. Você pode utilizar o operador condicional em qualquer lugar onde utilizaria um operador padrão.

Por exemplo,

```js
var status = idade >= 18 ? "adulto" : "menor de idade";
```

Esta declaração atribui o valor "adulto" à variável `status` caso `idade` seja dezoito ou mais. Caso contrário, atribui o valor "menor de idade".

### Operador vírgula

O operador vírgula (`,`) simplesmente avalia ambos de seus operandos e retorna o valor do segundo. Este operador é utilizado primariamente dentro de um laço `for` para permitir que multiplas variáveis sejam atualizadas cada vez através do laço.

Por exemplo, se `a` é uma matriz bidimensional com 10 elementos em um lado, o código a seguir utiliza o operador vírgula para incrementar duas variáveis de uma só vez. O código imprime os valores dos elementos diagonais da matriz:

```js
for (var i = 0, j = 9; i <= 9; i++, j--)
  console.log("a[" + i + "][" + j + "]= " + a[i][j]);
```

### Operadores unário

Um operador unário é uma operação com apenas um operando.

#### `delete`

O operador `delete` apaga um objeto, uma propriedade de um objeto ou um elemento no índice especificado de uma matriz. A sintaxe é:

```js
delete nomeObjeto;
delete nomeObjeto.propriedade;
delete nomeObjeto[indice];
delete propriedade; // válido apenas dentro de uma declaração with
```

onde `nomeObjeto` é o nome de um objeto, `propriedade` é uma propriedade existente e `indice` é um inteiro que representa a localização de um elemento em uma matriz.

A quarta forma é permitida somente dentro de uma declaração `with` para apagar uma propriedade de um objeto.

Você pode utilizar o operador `delete` para apagar variáveis declaradas implicitamente mas não aquelas declaradas com `var`.

Se o operador `delete` for bem-sucedido, ele define a propriedade ou elemento para `undefined`. O operador `delete` retorna verdadeiro se a operação for possível; ele retorna falso se a operação não for possível.

```js
x = 42;
var y = 43;
meuobj = new Number();
meuobj.h = 4; // cria a propriedade h
delete x; // retorna true (pode apagar se declarado implicitamente)
delete y; // retorna false (não pode apagar se declarado com var)
delete Math.PI; // retorna false (não pode apagar propriedades predefinidas)
delete meuobj.h; // retorna true (pode apagar propriedades definidas pelo usuário)
delete meuobj; // retorna true (pode apagar se declarado implicitamente)
```

##### Apagando elementos de array

Quando você apaga um elemento de um array, o tamanho do array não é afetado. Por exemplo, se você apaga `a[3]`, o valor de `a[4]` ainda estará em `a[4]` e `a[3]` passa a ser `undefined`.

Quando o operador `delete` remove um elemento do array, aquele elemento não pertence mais ao array. No exemplo a seguir, `arvores[3]` é removido com `delete`. Entretanto, `arvores[3]` ainda é endereçável e retorna `undefined`.

```js
var arvores = new Array(
  "pau-brasil",
  "loureiro",
  "cedro",
  "carvalho",
  "sicômoro",
);
delete arvores[3];
if (3 in arvores) {
  // isto não é executado
}
```

Se você quer que um elemento do array exista, mas tenha um valor indefinido, utilize a palavra-chave `undefined` em vez do operador `delete`. No exemplo a seguir, o valor `undefined` é atribuído a `arvores[3]`, mas o elemento da matriz ainda existe:

```js
var arvores = new Array(
  "pau-brasil",
  "loureiro",
  "cedro",
  "carvalho",
  "sicômoro",
);
arvores[3] = undefined;
if (3 in arvores) {
  // isto será executado
}
```

#### `typeof`

O operador `typeof` é utilizado em qualquer uma das seguintes formas:

```js
typeof operando;
typeof (operando);
```

O operador `typeof` retorna uma string indicando o tipo do operando sem avaliação. `operando` é uma string, variável, palavra-chave ou objeto cujo tipo deve ser retornado. Os parênteses são opcionais.

Suponha que você defina as seguintes variáveis:

```js
var meuLazer = new Function("5 + 2");
var forma = "redondo";
var tamanho = 1;
var hoje = new Date();
```

O operador `typeof` retornaria o seguinte resultado para aquelas variáveis:

```js
typeof meuLazer; // retorna "function"
typeof forma; // retorna "string"
typeof tamanho; // retorna "number"
typeof hoje; // retorna "object"
typeof naoExiste; // retorna "undefined"
```

Para as palavras-chave `true` e `null`, o `typeof` retorna os seguintes resultados:

```js
typeof true; // retorna "boolean"
typeof null; // retorna "object"
```

Para um número ou uma string, o `typeof` retorna os seguintes resultados:

```js
typeof 62; // retorna "number"
typeof "Olá mundo"; // retorna "string"
```

Para valores de propriedades, o `typeof` retorna o tipo do valor que a propriedade possui:

```js
typeof document.lastModified; // retorna "string"
typeof window.length; // retorna "number"
typeof Math.LN2; // retorna "number"
```

Para métodos e funções, o `typeof` retorna os seguintes resultados:

```js
typeof blur; // retorna "function"
typeof eval; // retorna "function"
typeof parseInt; // retorna "function"
typeof forma.split; // retorna "function"
```

Para objetos predefinidos, o `typeof` retorna os seguintes resultados:

```js
typeof Date; // retorna "function"
typeof Function; // retorna "function"
typeof Math; // retorna "object"
typeof Option; // retorna "function"
typeof String; // retorna "function"
```

#### `void`

O operador `void` é utilizado de qualquer uma das seguintes formas:

```js
void (expressao);
void expressao;
```

O operador `void` especifica que uma expressão deve ser avaliada sem retorno de valor. `expressao` é uma expressão JavaScript que deve ser avaliada. Os parênteses em torno da expressão são opcionais, mas é uma boa prática utilizá-los.

Você pode utilizar o operador `void` para especificar uma expressão como um link de hipertexto. A expressão é avaliada mas não é carregada no lugar do documento atual.

O código a seguir cria um link de hipertexto que não faz coisa alguma quando clicado pelo usuário. Quando o usuário clica no link, `void(0)` é avaliado como indefinido, que não tem efeito em JavaScript.

```html
<a href="javascript:void(0)">Clique aqui para fazer nada</a>
```

O código a seguir cria um link de hipertexto que submete um formulário quando clicado pelo usuário.

```html
<a href="javascript:void(document.form.submit())">Clique aqui para enviar</a>
```

### Operadores relacionais

Um operador relacional compara seus operando e retorna um valor booleano baseado em se a comparação é verdadeira.

#### `in`

O operador `in` retorna verdadeiro se a propriedade especificada estiver no objeto especificado. A sintaxe é:

```js
nomePropriedadeOuNumero in nomeObjeto;
```

onde `nomePropriedadeOuNumero` é uma string ou uma expressão numérica que representa um nome de propriedade ou um índice de um array, e `nomeObjeto` é o nome de um objeto.

Os exemplos a seguir mostram alguns usos do operador `in`.

```js
// Arrays
var arvores = new Array(
  "pau-brasil",
  "loureiro",
  "cedro",
  "carvalho",
  "sicômoro",
);
0 in arvores; // retorna verdadeiro
3 in arvores; // retorna verdadeiro
6 in arvores; // retorna falso
"cedro" in arvores; // retorna falso (você deve especificar o número do índice,
// não o valor naquele índice)
"length" in arvores; // retorna verdadeiro (length é uma propriedade de Array)

// Objetos predefinidos
"PI" in Math; // retorna verdadeiro
var minhaString = new String("coral");
"length" in minhaString; // retorna verdadeiro

// Objetos personalizados
var meucarro = { marca: "Honda", modelo: "Accord", ano: 1998 };
"marca" in meucarro; // retorna verdadeiro
"modelo" in meucarro; // retorna verdadeiro
```

#### `instanceof`

O operador `instanceof` retorna verdadeiro se o objeto especificado for do tipo de objeto especificado. A sintaxe é:

```js
nomeObjeto instanceof tipoObjeto;
```

onde `nomeObjeto` é o nome do objeto a ser comparado com `tipoObjeto`, e `tipoObjeto` é um tipo de objeto como `Date` ou `Array`.

Utilize o `instanceof` quando você precisar confirmar o tipo de um objeto em tempo de execução. Por exemplo, ao capturar exceções você pode desviar para um código de manipulação de exceção diferente dependendo do tipo de exceção lançada.

Por exemplo, o código a seguir utiliza o `instanceof` para determinar se `dia` é um objeto `Date`. Como `dia` é um objeto `Date`, as declarações do `if` são executadas.

```js
var dia = new Date(1995, 12, 17);
if (dia instanceof Date) {
  // declarações a serem executadas
}
```

### Precedência de operadores

A *precedência* de operadores determina a ordem em que eles são aplicados quando uma expressão é avaliada. Você pode substituir a precedência dos operadores utilizando parênteses.

A tabela a seguir descreve a precedência de operadores, da mais alta para a mais baixa.

| Tipo de operador | Operadores individuais |
| --- | --- |
| membro | `. []` |
| chamada / criação de instância | `() new` |
| negação / incremento | `! ~ - + ++ -- typeof void delete` |
| multiplicação / divisão / resto ou módulo | `* / %` |
| adição / subtração | `+ -` |
| deslocamento bit a bit | `<< >> >>>` |
| relacional | `< <= > >= in instanceof` |
| igualdade | `== != === !==` |
| E bit a bit | `&` |
| OU exclusivo bit a bit | `^` |
| OU bit a bit | `|` |
| E lógico | `&&` |
| OU lógico | `||` |
| condicional | `?:` |
| atribuição | `= += -= *= /= %= <<= >>= >>>= &= ^= |=` |
| vírgula | `,` |

Uma versão mais detalhada desta tabela, com links adicionais para detalhes de cada operador, pode ser vista em Referência do JavaScript (en-US).

Expressões
----------

Uma *expressão* consiste em qualquer unidade válida de código que é resolvida como um valor.

Conceitualmente, existem dois tipos de expressões: aquelas que atribuem um valor a uma variável e aquelas que simplesmente possuem um valor.

A expressão `x = 7` é um exemplo do primeiro tipo. Esta expressão utiliza o *operador* = para atribuir o valor sete à variável `x`. A expressão em si é avaliada como sete.

O código `3 + 4` é um exemplo do segundo tipo de expressão. Esta expressão utiliza o operador + para somar três e quatro sem atribuir o resultado, sete, a uma variável.

O JavaScript possui as seguintes categorias de expressão:

* Aritmética: é avaliada como um número, por exemplo 3.14159. (Geralmente utiliza operadores aritméticos).
* String: é avaliada como uma string de caracteres, por exemplo, "Fred" ou "234". (Geralmente utiliza operadores de string).
* Lógica: é avaliada como verdadeira ou falsa. (Costuma envolveroperadores lógicos).
* Expressões primárias: Palavras reservadas e expressões gerais do JavaScript.
* Expressão lado esquerdo: atribuição à esquerda de valores.
### Expressões primárias

Palavras reservadas e expressões gerais do JavaScript.

#### `this`

Utilize a palavra reservada `this` para se referir ao objeto atual. Em geral, o `this` se refere ao objeto chamado em um método. Utilize o `this` das seguintes formas:

```js
this["nomePropriedade"];
this.nomePropriedade;
```

Suponha uma função chamada `valide` que valida a propriedade `valor` de um objeto, dado o objeto e os valores máximo e mínimo:

```js
function valide(obj, minimo, maximo) {
  if (obj.valor < minimo || obj.valor > maximo) alert("Valor inválido!");
}
```

Você poderia chamar `valide` em cada manipulador de evento `onChange` de um formulário utilizando `this` para passar o elemento do formulário, como no exemplo a seguir:

```html
<b>Informe um número entre 18 e 99:</b>
<input type="text" name="idade" size="3" onChange="valide(this, 18, 99);" />
```

#### Operador de agrupamento

O operador de agrupamento `( )` controla a precedência de avaliação de expressões. Por exemplo, você pode substituir a precedência da divisão e multiplicação para que a adição e subtração sejam avaliadas primeiro.

```js
var a = 1;
var b = 2;
var c = 3;

// Precedência padrão
a + b \* c; // 7
// a avaliação padrão pode ser assim
a + (b \* c); // 7

// Agora substitui a precedência
// soma antes de multiplicar
(a + b) \* c; // 9

// o que é equivalente a
a \* c + b \* c; // 9
```

#### Comprehensions

Comprehensions são uma característica experimental de JavaScript, marcada para ser inclusa em uma versão futura do ECMAScript. Existem duas versões de Comprehensions:

Experimental
**`[for (x of y) x]` (en-US)**
 Comprehensions de array.

Experimental
\*\*`(for (x of y) y)` (en-US)
 \*\* `gerador de` comprehensions

Comprehensions existem em muitas linguagens de programação e permitem que você rapidamente monte um novo array com base em um existente, por exemplo:

```js
[for (i of [ 1, 2, 3 ]) i\*i ];
// [ 1, 4, 9 ]

var abc = [ "A", "B", "C" ];
[for (letras of abc) letras.toLowerCase()];
// [ "a", "b", "c" ]
```

### Expressão lado esquerdo

Atribuição à esquerda de valores.

#### `new`

Você pode utilizar o operador new para criar uma instância de um tipo de objeto definido pelo usuário ou de um dos tipos de objeto predefinidos: `Array`, `Boolean`, `Date`, `Function`, `Image`, `Number`, `Object`, `Option`, `RegExp` ou `String`. No servidor, você pode também utilizar `DbPool`, `Lock`, `File` ou `SendMail`. Utilize o operador `new` da seguinte forma:

```js
var nomeObjeto = new tipoObjeto([parametro1, parametro2, ..., parametroN]);
```

#### `super`

A palavra reservada super é utilizada para chamar a função pai de um objeto. É útil para nas classes para a chamada do construtor pai, por exemplo:
```

super([argumentos]); //chama o construtor pai.
super.funcaoDoPai([argumentos]);
```

#### `Operador spread`

O operador `spread` permite que uma expressão seja expandido em locais onde são esperados vários argumentos (para chamadas de função) ou vários elementos (para arrays).

Exemplo: Se você tem um array e deseja criar um novo array com os elementos do array já existente sendo parte do novo array, a sintaxe do array não será suficiente e você terá de usar uma combinação de push, splice, concat, etc. Com a sintaxe `spread`, isto torna-se muito mais sucinto:

```js
var partes = ["ombro", "joelhos"];
var musica = ["cabeca", ...partes, "e", "pés"];
```

Da mesma forma, o operador `spread` funciona com chamadas de função:

```js
function f(x, y, z) {}
var args = [0, 1, 2];
f(...args);
```

* « Previous
* Next »


Coleções Indexadas - JavaScript

Coleções Indexadas
==================

* « Previous
* Next »

Este capítulo introduz coleções de dados que são ordenados por um valor indexado. Isso inclui construtores de arrays e array-like como objetos `Array` e `TypedArray` (en-US).

Objeto `Array`
--------------

Um array é um conjunto de valores ordenados que você o referencia com um nome e um índice. Por exemplo, você pode ter um array chamado `emp` que contém nomes de funcionários indexados por seus números de funcionários. Então `emp[1]` poderia ser o funcionário número 1, `emp[2]` o funcionário número 2 e assim por diante.

JavaScript não possui um tipo de dados array específico. No entanto, você pode usar o objeto predefinido `Array` e seus métodos para trabalhar com arrays em suas aplicações. O objeto `Array` tem métodos para manipular arrays de várias maneiras como join, reverse e sort. Ele tem uma propriedade para determinar o tamanho do array e outras propriedades para usar com expressões regulares.

### Criando um array

As declarações a seguir criam arrays equivalentes:

```js
var arr = new Array(elemento0, elemento1, ..., elementoN);
var arr = Array(elemento0, elemento1, ..., elementoN);
var arr = [elemento0, elemento1, ..., elementoN];
```

`elemento0, elemento1, ..., elementoN` é uma lista de valores para os elementos do array. Quando esses valores são especificados, o array é inicializado com eles como elementos deste array. A propriedade do comprimento do array é definida pelo número de argumentos.

A sintaxe dos colchetes é chamada de "array literal" ou "inicializador de array". É uma abreviação de outras formas de criação de array e é a forma preferida de criação. Veja Array literal para detalhes.

Para criar um array com tamanho diferente de zero mas sem nenhum item, qualquer esquema abaixo pode ser utilizado:

```js
var arr = new Array(comprimentoDoArray);
var arr = Array(comprimentoDoArray);

// Estes produzem exatamente o mesmo efeito
var arr = [];
arr.length = comprimentoDoArray;
```

**Nota:** **Nota :** No código acima, `comprimentoDoArray` deve ser um `Número`. De outra maneira, um array com um único elemento (o valor passado) será criado. Chamar `arr.length` retornará `comprimentoDoArray`, mas o array na verdade, contem elementos vazios (undefined). Executar um loop `for...in` no array, não retornará nenhum dos elementos do array.

Além de poderem ser definidos como uma nova variável, como mostrado acima, arrays também podem ser atribuídos como uma propriedade de um novo objeto, ou de um objeto existente:

```js
var obj = {};
// ...
obj.prop = [elemento0, elemento1, ..., elementoN];

// OU
var obj = {prop: [elemento0, elemento1, ...., elementoN]}
```

Se você deseja inicializar um array com um único elemento, e este elemento é um `Número`, você precisa usar a sintáxe dos colchetes. Quando um único valor de `Número` é passado para o construtor do Array(), ou para uma função, ele é interpretado como um `comprimentoDoArray`, e não como um elemento único.

```js
var arr = [42]; // Cria um array com apenas um elemento:
// o número 42.

var arr = Array(42); // Cria um array sem elementos
// e arr.length é definido como 42; isso é
// equivalente a:
var arr = [];
arr.length = 42;
```

Chamar `Array(N)` resulta em um `RangeError`, se `N` é um número não inteiro cuja porção fracionária não é zero. O exemplo a seguir ilustra esse comportamento.

```js
var arr = Array(9.3); // RangeError: Invalid array length
```

Se o seu código precisa criar arrays com elementos singulares de um tipo de dados arbitrário, é mais seguro usar arrays literais. Ou então, crie um array vazio antes de adicionar um elemento singular nele.

### Povoando um array

Você pode povoar (inserir elementos) a um array atribuindo valores aos seus elementos. Por exemplo:

```js
var emp = [];
emp[0] = "Casey Jones";
emp[1] = "Phil Lesh";
emp[2] = "August West";
```

**Nota:** **Nota :** se você fornece um valor não inteiro ao operador do array, como no código acima, a propriedade será criada no objeto representando o array, ao invés do elemento do array.

```js
var arr = [];
arr[3.4] = "Oranges";
console.log(arr.length); // 0
console.log(arr.hasOwnProperty(3.4)); // verdadeiro
```

Você também pode povoar o array quando o cria:

```js
var myArray = new Array("Olá", myVar, 3.14159);
var myArray = ["Manga", "Maçã", "Laranja"];
```

### Referenciando os elementos do array

Você referencia os elementos do array através do uso de elementos numéricos ordinais. Por exemplo, suponha que você definiu o seguinte array:

```js
var myArray = ["Vento", "Chuva", "Fogo"];
```

Você então se refere ao primeiro elemento do array como em `myArray[0]` e ao segundo elemento do array como em `myArray[1]`. O índice do elemento começa com zero.

**Nota:** **Nota :** o operador do array (colchetes) também é usado para acessar as propriedades do array (arrays também são objetos em JavaScript). Por exemplo,

```js
var arr = ["um", "dois", "três"];
arr[2]; // três
arr["length"]; // 3
```

### Compreendendo o comprimento

Sobe o ponto de vista da implementação, arrays JavaScript armazenam na realidade elementos como propriedades de objetos padrões, usando o índice do array como o nome da propriedade. O comprimento da propriedade é especial: ele sempre retorna o índice do último mais um (no exemplo seguinte Dusty é indexado no 30, então cats.length retorna 30 + 1). Lembre-se, índices de arrays JavaScript são baseados no zero: eles começam no 0, não no 1. Isso significa que o comprimento da propriedade será um a mais que o maior índice armazenado no array:

```js
var gatos = [];
gatos[30] = ["Dusty"];
console.log(gatos.length); // 31
```

Você também pode atribuir um valor à propriedade `length`. Ao escrever um valor menor que o número de itens armazenados, trunca o array: escrevendo zero limpa-o completamente:

```js
var gatos = ["Dusty", "Misty", "Twiggy"];
console.log(gatos.length); // 3

gatos.length = 2;
console.log(gatos); // mostra "Dusty, Misty" - Twiggy foi removido

gatos.length = 0;
console.log(gatos); // nada é apresentado; o array gatos está vazio

gatos.length = 3;
console.log(gatos); // [undefined, undefined, undefined]
```

### Iteração em arrays

Uma operação comum é a de iterar sobre os valores de um array, processando cada elemento de alguma maneira. A maneira mais simples para fazer isso é como segue:

```js
var cores = ["vermelho", "verde", "azul"];
for (var i = 0; i < cores.length; i++) {
  console.log(cores[i]);
}
```

Se você sabe que nenhum dos elemnetos no seu array é avaliado como `false` em um contexto booleano — se o seu array consiste apenas de nodos do DOM, como exemplo, você pode usar um idioma mais eficiente:

```js
var divs = document.getElementsByTagName("div");
for (var i = 0, div; (div = divs[i]); i++) {
  /\* Processa div de alguma forma \*/
}
```

Isso evita a sobrecarga da checagem do comprimento do array, e garante que a variável div seja reatribuida ao item atual cada vez que o loop for adicionado por conveniência.

O método `forEach()` disponibiliza um outro jeito de iterar sobre/em um array:

```js
var cores = ["vermelho", "verde", "azul"];
cores.forEach(function (cor) {
  console.log(cor);
});
// vermelho
// verde
// azul
```

Alternativamente, você pode encurtar o código para o parâmetro do `forEach` com Arrow Functions ES6.

```js
var cores = ["vermelho", "verde", "azul"];
cores.forEach((cor) => console.log(cor));
// vermelho
// verde
// azul
```

A função passada para o `forEach` é executada uma vez para cada item no array, com o item do array passado como o argumento para a função. Valores não atribuídos não são iterados no loop `forEach`.

Note que os elementos de um array que foram omitidos quando o array foi definido, não são listados quando iterados pelo `forEach`, mas são listados quando `undefined` foi manualmente atribuído ao elemento:

```js
var array = ["primeiro", "segundo", , "quarto"];

array.forEach(function (elemento) {
  console.log(elemento);
});
// primeiro
// segundo
// quarto

if (array[2] === undefined) {
  console.log("array[2] is undefined"); // verdadeiro
}

array = ["primeiro", "segundo", undefined, "quarto"];

array.forEach(function (elemento) {
  console.log(elemento);
});
// primeiro
// segundo
// undefined
// quarto
```

Como elementos JavaScript são salvos como propriedades de objetos padronizados, não é aconselhável iterar sobre arrays JavaScript usando loops `for...in`, porque elementos normais e todas as propriedades numeráveis serão listadas.

### Métodos dos arrays

O objeto `Array` possui os seguintes métodos:

`concat()` une dois arrays e retorna um novo array.

```js
var myArray = new Array("1", "2", "3");
myArray = myArray.concat("a", "b", "c");
// myArray agora é ["1", "2", "3", "a", "b", "c"]
```

`join(deliminator = ',')` une todos os elementos de um array dentro de um string.

```js
var myArray = new Array("Vento", "Chuva", "Fogo");
var lista = myArray.join(" - "); // lista é "Vento - Chuva - Fogo"
```

`push()` adiciona um ou mais elementos no fim de um array e retorna o comprimento resultante do array.

```js
var myArray = new Array("1", "2");
myArray.push("3"); // myArray é agora ["1", "2", "3"]
```

`pop()` remove o último elemento de um array e retorna esse elemento.

```js
var myArray = new Array("1", "2", "3");
var ultimo = myArray.pop();
// myArray é agora ["1", "2"], ultimo = "3"
```

`shift()` remove o primeiro elemento de um array e retorna esse elemento.

```js
var myArray = new Array("1", "2", "3");
var primeiro = myArray.shift();
// myArray agora é ["2", "3"], primeiro é "1"
```

`unshift()` adiciona um ou mais elementos ao início do array e retorna o novo comprimento do array.

```js
var myArray = new Array("1", "2", "3");
myArray.unshift("4", "5");
// myArray torna-se ["4", "5", "1", "2", "3"]
```

`slice(start_index, upto_index)` extrai uma seção de um array e retorna um novo array.

```js
var myArray = new Array("a", "b", "c", "d", "e");
myArray = myArray.slice(1, 4); // inicia no índice 1 e extrai todos os elementos
// até o índice 3, retornado [ "b", "c", "d"]
```

`splice(index, count_to_remove, addElement1, addElement2, ...)` remove elementos de um array e (opcionalmente) o substitui, e retorna os itens que foram removidos do array.

```js
var myArray = new Array("1", "2", "3", "4", "5");
myArray.splice(1, 3, "a", "b", "c", "d");
// myArray é agora ["1", "a", "b", "c", "d", "5"]
// Este código iniciou no índice um (ou onde o "2" estava),
// removeu 3 elementos a partir dali, e então inseriu todos os elementos
// consecutivos em seus lugares.
```

`reverse()` transpõe (inverte) os elementos de um array, *in situ*: o primeiro elemento do array se torna o último e o último torna-se o primeiro, e retorna uma referência para o array.

```js
var myArray = new Array("1", "2", "3");
myArray.reverse();
// transpõe o array de modo que myArray = [ "3", "2", "1" ]
```

`sort()` ordena os elementos de um array *in situ*, e retorna uma referência para o array.

```js
var myArray = new Array("Neve", "Chuva", "Fogo");
myArray.sort();
// ordena o array de modo que myArray = [ "Chuva", "Fogo", "Neve" ]
```

`sort()` também pode 'pegar' uma função callback para determinar como os elementos do array são comparados.

O método sort, assim como outros métodos abaixo que tomam um callback são conhecidos como *métodos iterativos*, porque eles iteram sobre o array de alguma forma. Cada um pega um segundo argumento opcional chamado `thisObject`. Se fornecido, `thisObject` se torna o valor da palavra chave `this` dentro do corpo da função callback. Se não fornecido, como em outros casos onde uma função é invocada fora do contexto explícito de um objeto, `this` fará referência ao objeto global (`window`).

A função callback é na verdade chamada com três argumentos. O primeiro é o valor do item corrente, o segundo é o índice do array e o terceiro é uma referência ao próprio array. Funções javaScript ignoram qualquer argumento que não são nomeados na lista de parâmetros, portanto é seguro prover uma função callback que toma somente um único argumento, como a função `alert`.

A função abaixo compara dois valores e retorna um dos tres valores: -1, 0 ou 1.

Por exemplo, o seguinte trecho de código vai ordenar pela última letra da string:

```js
var sortFn = function (a, b) {
  if (a[a.length - 1] < b[b.length - 1]) return -1;
  if (a[a.length - 1] > b[b.length - 1]) return 1;
  if (a[a.length - 1] == b[b.length - 1]) return 0;
};
myArray.sort(sortFn);
// ordena o array de modo que myArray = ["Chuva","Neve","Fogo"]
```

* se `a` for menor que `b` pelo sistema de ordenação, retorna -1 (ou qualquer número negativo)
* se `a` for maior que `b` pelo sistema de ordenação, retorna 1 (ou qualquer número positivo)
* se `a` e `b` forem considerados equivalentes, retornará 0.

`indexOf(searchElement[, fromIndex])` busca `searchElement` no array e retorna o índice da primeira ocorrência.

```js
var a = ["a", "b", "a", "b", "a"];
console.log(a.indexOf("b")); // mostra 1
// Agora tente novamente, iniciando após o último resultado de busca
console.log(a.indexOf("b", 2)); // mostra 3
console.log(a.indexOf("z")); // mostra -1, porque 'z' não foi encontrado
```

`lastIndexOf(searchElement[, fromIndex])` funciona como `indexOf`, mas começa no fim e busca de trás para a frente.

```js
var a = ["a", "b", "c", "d", "a", "b"];
console.log(a.lastIndexOf("b")); // mostra 5
// Agora tente novamente, iniciando antes do último resultado de busca
console.log(a.lastIndexOf("b", 4)); // mostra 1
console.log(a.lastIndexOf("z")); // mostra -1
```

`forEach(callback[, thisObject])` executa um `callback` em cada item do array e retorna undefined.

```js
var a = ["a", "b", "c"];
a.forEach(function (element) {
  console.log(elemento);
});
// mostra cada item por vez
```

`map(callback[, thisObject])` retorna um novo array do valor retornado da execução do callback em cada item do array.

```js
var a1 = ["a", "b", "c"];
var a2 = a1.map(function (item) {
  return item.toUpperCase();
});
console.log(a2); // logs ['A', 'B', 'C']
```

`filter(callback[, thisObject])` retorna um novo array contendo os items verdadeiros ao executar o callback.

```js
var a1 = ["a", 10, "b", 20, "c", 30];
var a2 = a1.filter(function (item) {
  return typeof item === "number";
});
console.log(a2); // mostra [10, 20, 30]
```

`every(callback[, thisObject])` retorna verdadeiro se o `callback` retornar verdadeiro para cada item no array.

```js
function isNumber(valor) {
  return typeof valor === "number";
}
var a1 = [1, 2, 3];
console.log(a1.every(isNumber)); // mostra true
var a2 = [1, "2", 3];
console.log(a2.every(isNumber)); // mostra false
```

`some(callback[, thisObject])` retorna verdadeiro se o `callback` retornar verdadeiro para pelo menos um item no array.

```js
function isNumber(valor) {
  return typeof valor === "number";
}
var a1 = [1, 2, 3];
console.log(a1.some(isNumber)); // mostra true
var a2 = [1, "2", 3];
console.log(a2.some(isNumber)); // mostra true
var a3 = ["1", "2", "3"];
console.log(a3.some(isNumber)); // mostra false
```

`reduce(callback[, initialValue])` aplica `callback(firstValue, secondValue)` para reduzir a lista de itens para um único valor e retorna este valor.

```js
var a = [10, 20, 30];
var total = a.reduce(function (primeiro, segundo) {
  return primeiro + segundo;
}, 0);
console.log(total); // mostra 60
```

`reduceRight(callback[, initalvalue])` funciona como `reduce()`, mas inicia com o último elemento.

`reduce` e `reduceRight` são os métodos iterativos menos óbvios dos arrays. Eles devem ser usados para algorítmos que combinam dois valores de maneira recursiva com a finalidade de reduzir uma sequência para um único valor.

### Arrays multidimensionais

Arrays podem ser aninhados, significando que um array pode conter outro array como seu elemento. Usando essa característica dos arrays JavaScript, arrays multidimensionais pode ser criados.

O código a seguir cria dois arrays multidimensionais:

```js
var a = new Array(4);
for (i = 0; i < 4; i++) {
  a[i] = new Array(4);
  for (j = 0; j < 4; j++) {
    a[i][j] = "[" + i + "," + j + "]";
  }
}
```

Esse exemplo cria um array com as seguintes linhas:
```

Linha 0: [0,0] [0,1] [0,2] [0,3]
Linha 1: [1,0] [1,1] [1,2] [1,3]
Linha 2: [2,0] [2,1] [2,2] [2,3]
Linha 3: [3,0] [3,1] [3,2] [3,3]
```

### Arrays e expressões regulares

Quando um array é o resultado de uma equivalência entre uma expressão regular e um string, o array retorna propriedades e elementos que disponibilizam a informação sobre a correspondência. Um array é o valor retornado de `RegExp.exec()`, `String.match()`, e `String.split()`. Para informações sobre o uso de arrays com expressões regulares, veja Expressões Regulares.

### Trabalhando com objetos array-like

Alguns objetos JavaScript, como a `NodeList` retornada pelo `document.getElementsByTagName()` (en-US) ou o objeto acessível dentro do `arguments` de uma função, se parecem e se comportam superficialmente como arrays, mas não compartilham de todos os seus métodos. O objeto `arguments` fornece um atributo `length` mas não implementa o método `forEach()`, por exemplo.

Métodos Array prototype podem ser chamados contra outros objetos array-like. Por exemplo:

```js
function printArguments() {
  Array.prototype.forEach.call(arguments, function (item) {
    console.log(item);
  });
}
```

Métodos Array prototype também podem ser usados em strings, desde que eles forneçam acesso sequencial a seus caracteres de maneira similar às arrays:

```js
Array.prototype.forEach.call("uma string", function (chr) {
  console.log(chr);
});
```

Arrays Tipados
--------------

Arrays tipados no JavaScript são objetos array-like e provêm um mecanismo para acessar dados binários crus. Como você já sabe, objetos `Array` crescem e encolhem dinamicamente e podem ter um valor JavaScript. O motor do JavaScript executa otimizações para que os arrays sejam rápidos. Contudo, à medida que as aplicações web se tornam cada vez mais poderosas, com a adição de funcionalidades como manipulação de áudio e vídeo, acesso a dados crus usando WebSockets, etc., ficou claro que existem momentos em que seria útil para o código JavaScript ser capaz de rapida e facilmente manipular dados binários crus em arrays tipados.

### Buffers e views: arquitetura do array tipado

Para alcançar máxima flexibilidade e eficiência, as views de array tipado do JavaScript dividem a implementação em **buffers** e **views.** Um buffer (implementado pelo objeto `ArrayBuffer`) é um objeto que representa um monte de dados; não possui nenhum formato específico e não oferece nenhum mecanismo para acessar seu conteúdo. Para acessar a memória contida em um buffer, você precisa usar uma view. Uma view provê um contexto — ou seja, um tipo de dado, um offset inicial e número de elementos — que transforma o dado em um array tipado real.

![Typed arrays in an ArrayBuffer](/pt-BR/docs/Web/JavaScript/Guide/Indexed_collections/typed_arrays.png)

### ArrayBuffer

O `ArrayBuffer` é um tipo de dado usado para representar um buffer de dados binários de tamanho fixo genérico. Você não pode manipular diretamente o conteúdo de um `ArrayBuffer;` ao invés disso, você deve criar uma view de array tipado ou uma `DataView` que represente o buffer em um formato específico, e use esta view para ler e modificar o conteúdo do buffer.

### Views de arrays tipados

Views de arrays tipados possuem nomes autodescritivos e provêm views para todos os tipos numéricos usuais como `Int8`, `Uint32`, `Float64` e assim por diante. Existe uma view de array tipado especial, o `Uint8ClampedArray`. Ela fixa os valores entre 0 e 255. Isto é útil para Canvas data processing (en-US), por exemplo.

{{page("/pt-BR/docs/Web/JavaScript/Reference/Global\_Objects/TypedArray", "TypedArray\_objects")}}
Para mais informações, veja Arrays tipados no JavaScript e documentos de referência para os diferentes objetos `TypedArray` (en-US).

* « Previous
* Next »


Números e datas - JavaScript

Números e datas
===============

* « Previous
* Next »

Este capítulo apresenta como utilizar números e datas em JavaScript.

Números
-------

Em Javascript, todos os números são implementados em double-precision 64-bit binary format IEEE 754 (Por exemplo, um número entre -(253 -1) e 253 -1). **Não havendo especificação de tipo Integer**. Além de ser capaz de representar números de ponto flutuante, o tipo de número tem três valores simbólicos: `+``Infinity`, `-``Infinity`, and `NaN` (not-a-number). Veja também Estruturas e Tipos de Dados em Javascript em contexto com outros tipos primitivos em JavaScript.

Você pode usar quatro tipos de números literais: decimal, binário, octal, e hexadecimal.

### Números Decimais

```js
1234567890;
42;

// Cuidado quando usar zeros à esquerda:

0888; // 888 interpretado como decimal
0777; // interpretado como octal em modo no-strict (511 em decimal)
```

Note que literais decimais podem começar com zero (`0`) seguido por outro digito decimal, porém se o próximo dígito depois do primeiro zero for menor do que 8, o número será analisado como um número octal.

### Números Binários

A sintaxe para números Binários, usa um zero à esquerda seguido de uma letra minúscula ou maiúscula "B" (`0b` or `0B`). Se os dígitos depois de 0b não forem 0 ou 1, a seguinte exceção `SyntaxError` (en-US) é lançada: "Missing binary digits after 0b".

```js
var FLT\_SIGNBIT = 0b10000000000000000000000000000000; // 2147483648
var FLT\_EXPONENT = 0b01111111100000000000000000000000; // 2139095040
var FLT\_MANTISSA = 0b00000000011111111111111111111111; // 8388607
```

### Números octais

A sintaxe dos números octais usa um zero na frente. Se os dígitos depois do 0 estiverem fora do alcance 0 a 7, o número será interpretado como um número decimal.

```js
var n = 0755; // 493
var m = 0644; // 420
```

Modo estrito no ECMAScript 5 proíbe a sintaxe octal. A sintaxe Octal não é parte do ECMAScript 5, mas é suportada por todos os navegadores prefixando o número octal com zero: `0644 === 420` e `"\045" === "%"`. Em ECMAScript 6 números Octais são suportados prefixando o número com "`0`o" isto é.

```js
var a = 0o10; // ES6: Octal
```

### Numeros hexadecimais

A sintaxe numérica Hexadecimal usa um 0 na frente seguido por uma letra "X" maiúscula ou minúscula (`0x` ou `0X)`. Se os dígidos depois do 0x estiverem fora do alcance (0123456789ABCDF), o seguinte erro de sintaxe (`SyntaxError` (en-US)) ocorrerá: "Identifier starts immediately after numeric literal" (O identificador começa imediatamente depois do literal numérico).

```js
0xfffffffffffffffff; // 295147905179352830000
0x123456789abcdef; // 81985529216486900
0xa; // 10
```

### Exponenciação

```js
1e3; // 1000
2e6; // 2000000
0.1e2; // 10
```

`Objeto Number`
---------------

Um objeto built-in `Number` tem propriedades para constantes numéricas, tais como valor máximo, não número e infinito. Você não pode alterar os valores dessas propriedades e elas são usadas assim:

```js
var maiorNum = Number.MAX\_VALUE; //Valor máximo
var menorNum = Number.MIN\_VALUE; //Valor mínimo
var infiniteNum = Number.POSITIVE\_INFINITY; //Infinito positivo
var negInfiniteNum = Number.NEGATIVE\_INFINITY; //Infinito negativo
var notANum = Number.NaN; //Não é numeral
```

Você sempre se refere a uma propriedade do objeto predefinido `Number` como mostrado acima, e não como uma propriedade de um objeto `Number que você mesmo criou.`

A tabela à seguir sumariza as propriedades do objeto `Number.`

| Propriedade | Descrição |
| --- | --- |
| `Number.MAX_VALUE` | O maior número representável. |
| `Number.MIN_VALUE` | O menor número representável. |
| `Number.NaN` | Valor "not a number" especial |
| `Number.NEGATIVE_INFINITY` | Valor especial infinito negativo; retornado em overflow |
| `Number.POSITIVE_INFINITY` | Valor especial infinito positivo; retornado em overflow |
| `Number.EPSILON` | Diferença entre um e o menor valor maior do que um que pode ser representado como um `Number`. |
| `Number.MIN_SAFE_INTEGER` | Mínimo safe integer em JavaScript. |
| `Number.MAX_SAFE_INTEGER` | Máximo safe integer em JavaScript. |

| Método | Descrição |
| --- | --- |
| `Number.parseFloat()` | Analisa um argumento string e retorna um número float. O mesmo que a função global `parseFloat()`. |
| `Number.parseInt()` | Analisa um argumento string e retorna um inteiro da raiz ou base especificada. O mesmo que a função global`parseInt()`. |
| `Number.isFinite()` | Determina se o valor passado é um número finito. |
| `Number.isInteger()` | Determina se o valor passado é um inteiro. |
| `Number.isNaN()` | Determina se o valor passado é `NaN`. A versão mais robusta da original `isNaN()`. |
| `Number.isSafeInteger()` | Determina se o valor passado é um safe integer. |

O protótipo `Number` provê métodos para resgatar informações de objetos `Number` em vários formatos. A tabela a seguir sumariza os métodos de `Number.prototype`.

| Método | Descrição |
| --- | --- |
| `toExponential()` (en-US) | Retorna uma string representando o número em uma notação exponencial. |
| `toFixed()` | Retorna uma string representando o número em notação com ponto-fíxo. |
| `toPrecision()` | Retorna uma string representando o número em uma precisão especificada na notação de ponto-fíxo. |

`Objeto Math`
-------------

O objeto `Math` tem propriedades e métodos para constantes matemáticas e funções. Por exemplo, o `PI do objeto` Math tem o valor de pi (3,141...), que você usaria em uma aplicação como

```js
Math.PI;
```

Similarmente, funções matemáticas padrão são métodos do Math. Isto inclui funções trigonométricas, logarítmicas, exponenciais, e outras funções. Por exemplo, se você quiser usar a função trigonométrica seno, basta escrever

```js
Math.sin(1.56);
```

Note que todos os métodos trigonométricos pegam argumentos em radianos.

A tabela a seguir sumariza os métodos do objeto Math.

| Método | Descrição |
| --- | --- |
| `abs()` | Valor absoluto |
| `sin()`, `cos()`, `tan()` | Funções trigonométricas padrão; Argumentos em radianos |
| `asin()`, `acos()`, `atan()`, `atan2()` | Funções trigonométricas inversas; retorna valores em radianos |
| `sinh()`, `cosh()`, `tanh()` | Funções trigonométricas hiperbólicas; retorna valores em radianos. |
| `asinh()`, `acosh()`, `atanh()` | Funções trigonométricas hiperbólicas inversas; retorna valores em radianos. |
| `pow()`, `exp()`, `expm1()`, `log10()`, `log1p()`, `log2()` | Funções exponenciais e logarítmicas. |
| `floor()`, `ceil()` | Retorna o maior/menor inteiro que é menor/maior inteiro que ou igual ao argumento. |
| `min()`, `max()` | Retorna menor ou maior (respectivamente) de uma lista separada por vírgula de argumentos numéricos |
| `random()` | Retorna um número aleatório entre 0 e 1. |
| `round()`, `fround()` (en-US), `trunc()`, | Funções de arredondamento e truncamento. |
| `sqrt()`, `cbrt()`, `hypot()` | Raiz quadrada, raiz cúbica, raiz quadrada da soma de argumentos ao quadrado. |
| `sign()` | O sinal de um número, indicando se o número é positivo, negativo ou zero. |
| `clz32()`, `imul()` (en-US) | Número de zeros à esquerda na representação binária de 32-bits. The result of the C-like 32-bit multiplication of the two arguments. |

Diferentemente de muitos outros objetos, você nunca cria um objeto Math por conta própria. Você sempre deve utilizar o objeto Math nativo.

`Objeto Date`
-------------

JavaScript não possui dados do tipo data. No entanto, você pode usar o objeto `Date` e seus métodos para trabalhar com datas e horas nas suas aplicações. O objeto Date tem um grande número de métodos para setar, recuperar e manipular datas. Ele não tem nenhuma propriedade.

JavaScript manipula datas de maneira semelhante ao Java. As duas linguagens tem muitos dos mesmos métodos para lidar com datas e ambas armazenam datas como números em milisegundos, desde 1 de janeiro de 1970, às 00:00:00 ( January 1, 1970, 00:00:00).

A abrangência do objeto Date é de -100,000,000 dias até 100,000,000 dias relativos a 01 de janeiro de 1970 UTC.

Para criar um objeto Date:

```js
var dateObjectName = new Date([parameters]);
```

onde `dateObjectName` é o nome do objeto Date que está sendo criado; ele pode ser um novo objeto ou uma propriedade de um objeto existente.

A chamada de Date sem a palavra reservada `new`, simplesmente converte a data para uma representação dela como string.

Os `parâmetros` do código acima podem ser qualquer um a seguir:

* Nada: cria a data e hora de hoje. Por exemplo, `today = new Date();.`
* Uma string representando uma data da seguinte forma: "Mês dia, ano, horas:minutos:segundos". Por exemplo, `Xmas95 = new Date("25 de dezembro de 1995, 13:30:00")`. Se você omitir as horas, minutos ou segundos, o valor será setado para zero.
* Um conjunto de valores inteiros para ano, mês e dia. Por exemplo, `var Xmas95 = new Date(1995, 11, 25)`.
* Um conjunto de valores inteiros par ano, mês, dia, hora, minuto e segundos. Por exemplo, `var Xmas95 = new Date(1995, 11, 25, 9, 30, 0);`.
### Métodos do objeto Date

Os métodos do objeto Date para manipular data e hora pertencem às seguintes categorias:

* Métodos "set", para setar valores de data e hora em objetos Date.
* Métodos "get", para recuperar valores de data e hora de objetos Date.
* Métodos "to", para retornar valores de string de objetos Date.
* Métodos parse e UTC, para parsear string de Data.

Com os métods "get" e "set", você pode recuperar e setar segundos, minutos, horas, dia e mês, dia da semana, meses e anos, separadamente. Existe um método `getDay` que retorna o dia da semana, mas não existe um método `setDay` correspondente, porque o dia da semana é setado automaticamente. Estes métodos utilizam números inteiros para representar estes valores da seguinte maneira:

* Segundos e minutos: de 0 a 59
* Horas: de 0 a 23
* Dia: 0 (Domingo) a 6 (Sábado)
* Data: 1 a 31 (dia do mês)
* Meses: 0 (Janeiro) a 11 (Dezembro)
* Ano: anos desde 1900

Por exemplo, suponha que você queira definir a seguinite data:

```js
var Xmas95 = new Date("December 25, 1995");
```

Então `Xmas95.getMonth()` retorna 11 e `Xmas95.getFullYear()` retorna 1995.

Os métodos `getTime` e `setTime` são úteis para comparar datas. O método `getTime` retorna o número dos milisegundos desde 1 de janeiro de 1970, às 00:00:00 para um objeto Date.

Por exemplo, o código a seguir mostra os números dos dias que ainda faltam do ano vigente:

```js
var hoje = new Date();
var fimAno = new Date(1995, 11, 31, 23, 59, 59, 999); // Seta dia e mês
fimAno.setFullYear(hoje.getFullYear()); // Seta o ano para esse ano
var msPorDia = 24 \* 60 \* 60 \* 1000; // Quantidade de milisegundos por dia
var diasRestantes = (fimAno.getTime() - hoje.getTime()) / msPorDia;
var diasRestantes = Math.round(diasRestantes); //retorna os dias restantes no ano
```

Este exemplo cria um objeto Date chamado `hoje` que contém a data de hoje. Ele, então, cria o objeto Date chamado `fimAno`e seta o ano para o ano vigente. Então, usando o número de milisegundos por dia, ele computa o número de dias entre hoje e `fimAno`, usando `getTime` e arredondando os números de dias.

O método `parse` é útil para associar valores de strings de data para objetos Date existentes. Por exemplo, o código a seguir usa `parse` e `setTime` para associar um valor de data ao objeto `IPOdate`:

```js
var IPOdate = new Date();
IPOdate.setTime(Date.parse("Aug 9, 1995"));
```

No exemplo a seguir, a função `JSClock()` retorna o tempo no formato de um relógio digital.

```js
function JSClock() {
  var tempo = new Date();
  var hora = tempo.getHours();
  var minuto = tempo.getMinutes();
  var segundo = tempo.getSeconds();
  var temp = "" + (hora > 12 ? hora - 12 : hora);
  if (hora == 0) temp = "12";
  temp += (minuto < 10 ? ":0" : ":") + minuto;
  temp += (segundo < 10 ? ":0" : ":") + segundo;
  temp += hora >= 12 ? " P.M." : " A.M.";
  return temp;
}
```

A função `JSClock` primeiro cria um objeto new `Date` chamado tempo; já que nenhum argumento é passado, `tempo` é criado com data e hora atuais. Ela então chama os métodos `getHours`, `getMinutes` e `getSeconds` e associa o valor à hora, minuto e segundo atuais à hora, minuto e segundo.

As próximas quatro declarações constroem uma string baseada em time. A primeira declaração cria uma variável `temp`, associando um valor utilizando uma expressão condicional; se hora é maior que 12, (hora - 12), senão simplesmente hora, a não ser que hora seja 0 que, nesse caso, será 12.

A próxima declaração anexa um valor `minuto` a `temp`. Se o valor de minuto for menos que 10, a expressão condicional acrescenta uma string com um 0 na frente; senão ela acrescenta uma string com dois pontos. Então a declaração anexa um valor `segundo` a `temp` do mesmo jeito.

Finalmente, a expressão condicional anexa "P.M." a `temp` se `hora` for 12 ou maior; senão ela anexa "A.M." a `temp`.

* « Previous
* Next »


Módulos JavaScript - JavaScript

Módulos JavaScript
==================

* « Previous

Este guia fornece tudo o que você precisa para começar com a sintaxe de módulo do JavaScript.

Um background em módulos
------------------------

Os programas JavaScript começaram muito pequenos - a maior parte do seu uso nos primeiros dias era para executar tarefas isoladas de script, fornecendo um pouco de interatividade às suas páginas da Web sempre que necessário, de modo que scripts grandes geralmente não eram necessários. Com o avanço rápido da tecnologia agora temos aplicativos completos sendo executados em navegadores com muito JavaScript, além de JavaScript ser usado em outros contextos (Node.js, por exemplo).

Portanto, fez sentido nos últimos anos começar a pensar em fornecer mecanismos para dividir programas JavaScript em módulos separados que podem ser importados quando necessário. O Node.js possui essa capacidade há muito tempo e existem várias bibliotecas e estruturas JavaScript que permitem o uso do módulo (por exemplo, outros CommonJS e AMD-sistemas de módulos baseados em RequireJS, e mais recentemente Webpack e Babel).

A boa notícia é que os navegadores modernos começaram a dar suporte nativamente à funcionalidade do módulo, e é sobre isso que este artigo trata. Isso só pode ser uma coisa boa - os navegadores podem otimizar o carregamento de módulos, tornando-o mais eficiente do que ter que usar uma biblioteca e fazer todo esse processamento extra no lado do cliente e viagens de ida e volta extras.

Suporte do navegador
--------------------

O uso de módulos JavaScript nativos depende do`import` e `export` afirmações; estes são suportados nos navegadores da seguinte maneira:

### importa

### javascript.statements.import

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### javascript.statements.export

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### exporta

### javascript.statements.import

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### javascript.statements.export

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Apresentando um exemplo
-----------------------

Para demonstrar o uso dos módulos, criamos um conjunto simples de exemplos que você pode encontrar no GitHub. Estes exemplos demonstram um conjunto simples de módulos que criam um`<canvas>` em uma página da Web e desenhe (e relate informações sobre) formas diferentes na tela.

Estes são bastante triviais, mas foram mantidos deliberadamente simples para demonstrar claramente os módulos.

**Nota:** **Nota: Se você deseja fazer o download dos exemplos e executá-los localmente, precisará executá-los por meio de um servidor da web local.**

Exemplo de uma estrutura básica
-------------------------------

No nosso primeiro exemplo (consulte basic-modules) nós temos uma estrutura de arquivos da seguinte maneira:
```

index.html
main.js
modules/
    canvas.js
    square.js
```

**Nota:** **Nota: Todos os exemplos neste guia têm basicamente a mesma estrutura; o exposto acima deve começar a ficar bem familiar.**

Os dois módulos do diretório modules são descritos abaixo:

* `canvas.js` — contém funções relacionadas à configuração da tela:
    + `create()` — cria uma tela com uma largura e altura especificadas dentro de um invólucro `<div>` com um ID especificado, que é anexado dentro de um elemento pai especificado. Retorna um objeto que contém o contexto 2D da tela e o ID do wrapper.
    + `createReportList()` — cria uma lista não ordenada anexada dentro de um elemento de wrapper especificado, que pode ser usado para gerar dados de relatório. Retorna o ID da lista.
* `square.js` — contém:
    + `name` — uma constante contendo a string 'square'.
    + `draw()` — desenha um quadrado em uma tela especificada, com um tamanho, posição e cor especificados. Retorna um objeto que contém o tamanho, a posição e a cor do quadrado.
    + `reportArea()` — grava a área de um quadrado em uma lista de relatórios específica, considerando seu tamanho.
    + `reportPerimeter()` — grava o perímetro de um quadrado em uma lista de relatórios específica, considerando seu comprimento.
Aside — `.mjs` versus `.js`
---------------------------

Neste artigo, usamos extensões .js para nossos arquivos de módulo, mas em outros recursos você pode ver a extensão .mjs usada. A documentação da V8 recomenda isso, por exemplo. Os motivos apresentados são:

* É bom para maior clareza, ou seja, deixa claro quais arquivos são módulos e quais são JavaScript regulares.
* Ele garante que seus arquivos de módulo sejam analisados como um módulo por tempos de execução, como Node.js, e construir ferramentas como Babel.

No entanto, decidimos continuar usando .js, pelo menos por enquanto. Para que os módulos funcionem corretamente em um navegador, você precisa garantir que seu servidor os esteja servindo com um cabeçalho Content-Type que contenha um tipo MIME JavaScript, como text / javascript. Caso contrário, você receberá um erro estrito de verificação do tipo MIME, de acordo com as linhas "O servidor respondeu com um tipo MIME não JavaScript" e o navegador não executará seu JavaScript. A maioria dos servidores já define o tipo correto para arquivos .js, mas ainda não para arquivos .mjs. Servidores que já veiculam arquivos .mjs incluem corretamente GitHub Pages e `http-server` para Node.js.

Tudo bem se você já estiver usando esse ambiente ou se não estiver, mas souber o que está fazendo e tiver acesso (ou seja, você pode configurar o servidor para definir a configuração correta `Content-Type` para arquivos `.mjs`). No entanto, isso pode causar confusão se você não controlar o servidor do qual está servindo arquivos ou publicar arquivos para uso público, como estamos aqui.

Para fins de aprendizado e portabilidade, decidimos manter o`.js`.

Se você realmente valoriza a clareza de usar .mjs para módulos versus usar .js para arquivos JavaScript "normais", mas não deseja se deparar com o problema descrito acima, sempre poderá usar .mjs durante o desenvolvimento e convertê-los em .js durante sua etapa de construção.

Também é importante notar que:

* Algumas ferramentas podem nunca suportar .mjs, comoTypeScript.
* O atributo `<script type="module">`é usado para indicar quando um módulo está sendo apontado, como você verá abaixo.
Exportando recursos do módulo
-----------------------------

A primeira coisa que você faz para obter acesso aos recursos do módulo é exportá-los. Isso é feito usando o `export` declaração.

A maneira mais fácil de usá-lo é colocá-lo na frente de qualquer item que você queira exportar para fora do módulo, por exemplo:

```js
export const name = "square";

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return {
    length: length,
    x: x,
    y: y,
    color: color,
  };
}
```

Você pode exportar funções, `var`, `let`, `const`, e — como veremos mais tarde - classes. Eles precisam ser itens de nível superior; você não pode usar a exportação dentro de uma função, por exemplo.

Uma maneira mais conveniente de exportar todos os itens que você deseja exportar é usar uma única instrução de exportação no final do arquivo do módulo, seguida por uma lista separada por vírgula dos recursos que você deseja exportar envoltos em chaves. Por exemplo:

```js
export { name, draw, reportArea, reportPerimeter };
```

Importando recursos para o seu script
-------------------------------------

Depois de exportar alguns recursos do seu módulo, é necessário importá-los para o script para poder usá-los. A maneira mais simples de fazer isso é a seguinte:

```js
import { name, draw, reportArea, reportPerimeter } from "./modules/square.js";
```

Você usa o `import` , seguida por uma lista separada por vírgula dos recursos que você deseja importar agrupados em chaves, seguidos pela palavra-chave de, seguida pelo caminho para o arquivo do módulo - um caminho relativo à raiz do site, que para nossa `basic-modules` exemplo seria`/js-examples/modules/basic-modules`.

No entanto, escrevemos o caminho de maneira um pouco diferente - estamos usando a sintaxe de ponto (.) Para significar "o local atual", seguido pelo caminho além do arquivo que estamos tentando encontrar. Isso é muito melhor do que escrever todo o caminho relativo a cada vez, pois é mais curto e torna o URL portátil - o exemplo ainda funcionará se você o mover para um local diferente na hierarquia do site.

Então, por exemplo:
```

/js-examples/modules/basic-modules/modules/square.js
```

torna-se
```

./modules/square.js
```

Você pode ver essas linhas em ação em `main.js`.

**Nota:** **Nota: Em alguns sistemas de módulos, você pode omitir a extensão do arquivo e o ponto**(e.g. `'/modules/square'`). Isso não funciona nos módulos JavaScript nativos.

 Depois de importar os recursos para o seu script, você pode usá-los exatamente como eles foram definidos no mesmo arquivo. O seguinte é encontrado em
 `main.js`, abaixo das linhas de importação:

```js
let myCanvas = create("myCanvas", document.body, 480, 320);
let reportList = createReportList(myCanvas.id);

let square1 = draw(myCanvas.ctx, 50, 50, 100, "blue");
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
```

**Nota:** **Nota: Embora os recursos importados estejam disponíveis no arquivo, eles são visualizações somente leitura do recurso que foi exportado. Você não pode alterar a variável importada, mas ainda pode modificar propriedades semelhantes à const. Além disso, esses recursos são importados como ligações ativas, o que significa que eles podem mudar de valor mesmo que você não possa modificar a ligação ao contrário de const.**

Aplicando o módulo ao seu HTML
------------------------------

Agora, apenas precisamos aplicar o módulo main.js. à nossa página HTML. Isso é muito semelhante ao modo como aplicamos um script regular a uma página, com algumas diferenças notáveis.

Primeiro de tudo, você precisa incluir `type="module"` no `<script>` elemento, para declarar esse script como um módulo. Para importar o `main.js` script, usamos este:

```html
<script type="module" src="main.js"></script>
```

Você também pode incorporar o script do módulo diretamente no arquivo HTML, colocando o código JavaScript no corpo do elemento <script>:

```js
<script type="module">/\* JavaScript module code here \*/</script>
```

O script para o qual você importa os recursos do módulo atua basicamente como o módulo de nível superior. Se você o omitir, o Firefox, por exemplo, exibirá um erro "SyntaxError: as declarações de importação podem aparecer apenas no nível superior de um módulo".

Você só pode usar `import` e `export` instruções dentro de módulos, não scripts regulares.

Outras diferenças entre módulos e scripts padrão
------------------------------------------------

* Você precisa prestar atenção nos testes locais - se você tentar carregar o arquivo HTML localmente (i.e. com um arquivo`://` URL), você encontrará erros do CORS devido a requisitos de segurança do módulo JavaScript. Você precisa fazer seus testes através de um servidor.
* Além disso, observe que você pode obter um comportamento diferente das seções de script definidas dentro dos módulos e não nos scripts padrão. Isso ocorre porque os módulos usam strict mode automaticamente.
* Não há necessidade de usar o atributo deferir (consulte `<script>` attributes) ao carregar um script de módulo; módulos são adiados automaticamente.
* Os módulos são executados apenas uma vez, mesmo que tenham sido referenciados em várias tags <script>.
* Por último, mas não menos importante, vamos esclarecer: os recursos do módulo são importados para o escopo de um único script - eles não estão disponíveis no escopo global. Portanto, você poderá acessar apenas os recursos importados no script para o qual eles foram importados e não poderá acessá-los no console JavaScript, por exemplo. Você ainda receberá erros de sintaxe mostrados no DevTools, mas não poderá usar algumas das técnicas de depuração que você esperava usar.
Exportações padrão versus exportações nomeadas
----------------------------------------------

A funcionalidade que exportamos até agora foi composta por **named exports** — cada item (seja uma função, const, etc.) foi referido por seu nome na exportação e esse nome também foi usado para se referir a ele na importação.

Há também um tipo de exportação chamado **default export** — isso foi projetado para facilitar a função padrão fornecida por um módulo e também ajuda os módulos JavaScript a interoperar com os sistemas de módulos CommonJS e AMD existentes (conforme explicado em ES6 In Depth: Modules por Jason Orendorff; procure por "Exportações padrão").

Vejamos um exemplo ao explicar como ele funciona. Nos nossos módulos básicos `square.js` você pode encontrar uma função chamada `randomSquare()` que cria um quadrado com cor, tamanho e posição aleatórios. Queremos exportar isso como padrão, portanto, na parte inferior do arquivo, escrevemos isso:

```js
export default randomSquare;
```

Note a falta dos colchetes.

Em vez disso, poderíamos acrescentar `export default` na função e defina-a como uma função anônima, assim:

```js
export default function(ctx) {
  ...
}
```

No nosso arquivo main.js., importamos a função padrão usando esta linha:

```js
import randomSquare from "./modules/square.js";
```

Isso ocorre porque há apenas uma exportação padrão permitida por módulo e sabemos que *randomSquare* é isso.

```js
import { default as randomSquare } from "./modules/square.js";
```

**Nota:** **Nota: A sintaxe as para renomear itens exportados é explicada abaixo no** Renaming imports and exports seção.

Evitando conflitos de nomenclatura
----------------------------------

Até agora, nossos módulos de desenho de forma de tela parecem estar funcionando bem. Mas o que acontece se tentarmos adicionar um módulo que lide com o desenho de outra forma, como um círculo ou triângulo? Essas formas provavelmente teriam funções associadas, como `draw()`, `reportArea()`, etc. também; se tentássemos importar diferentes funções com o mesmo nome para o mesmo arquivo de módulo de nível superior, acabaríamos com conflitos e erros.

Felizmente, existem várias maneiras de contornar isso. Veremos isso nas próximas seções.

Renomeando importações e exportações
------------------------------------

Dentro dos colchetes da instrução de importação e exportação, você pode usar a palavra-chave junto com um novo nome de recurso, para alterar o nome de identificação que será usado para um recurso dentro do módulo de nível superior.

Por exemplo, os dois itens a seguir executariam o mesmo trabalho, embora de uma maneira ligeiramente diferente:

```js
// inside module.js
export { function1 as newFunctionName, function2 as anotherNewFunctionName };

// inside main.js
import { newFunctionName, anotherNewFunctionName } from "./modules/module.js";
```

```js
// inside module.js
export { function1, function2 };

// inside main.js
import {
  function1 as newFunctionName,
  function2 as anotherNewFunctionName,
} from "./modules/module.js";
```

Vejamos um exemplo real. Na nossa renaming diretório, você verá o mesmo sistema de módulos do exemplo anterior, exceto que adicionamos `circle.js` e `triangle.js` módulos para desenhar e relatar círculos e triângulos.

Dentro de cada um desses módulos, temos recursos com os mesmos nomes sendo exportados e, portanto, cada um tem o mesmo `export` declaração na parte inferior:

```js
export { name, draw, reportArea, reportPerimeter };
```

Ao importá-los para o main.js, se tentarmos usar

```js
import { name, draw, reportArea, reportPerimeter } from "./modules/square.js";
import { name, draw, reportArea, reportPerimeter } from "./modules/circle.js";
import { name, draw, reportArea, reportPerimeter } from "./modules/triangle.js";
```

O navegador geraria um erro como "SyntaxError: redeclaration of import name" (Firefox).

Em vez disso, precisamos renomear as importações para que sejam únicas:

```js
import {
  name as squareName,
  draw as drawSquare,
  reportArea as reportSquareArea,
  reportPerimeter as reportSquarePerimeter,
} from "./modules/square.js";

import {
  name as circleName,
  draw as drawCircle,
  reportArea as reportCircleArea,
  reportPerimeter as reportCirclePerimeter,
} from "./modules/circle.js";

import {
  name as triangleName,
  draw as drawTriangle,
  reportArea as reportTriangleArea,
  reportPerimeter as reportTrianglePerimeter,
} from "./modules/triangle.js";
```

Observe que você pode resolver o problema nos arquivos do módulo, e.g.

```js
// in square.js
export {
  name as squareName,
  draw as drawSquare,
  reportArea as reportSquareArea,
  reportPerimeter as reportSquarePerimeter,
};
```

```js
// in main.js
import {
  squareName,
  drawSquare,
  reportSquareArea,
  reportSquarePerimeter,
} from "./modules/square.js";
```

E funcionaria da mesma forma. Qual o estilo que você usa depende de você, no entanto, sem dúvida faz mais sentido deixar o código do módulo em paz e fazer as alterações nas importações. Isso faz especialmente sentido quando você está importando de módulos de terceiros sobre os quais você não tem controle.

24/5000

Criando um objeto de módulo

O método acima funciona bem, mas é um pouco confuso e longo. Uma solução ainda melhor é importar os recursos de cada módulo dentro de um objeto de módulo. O seguinte formulário de sintaxe faz isso:

```js
import \* as Module from "./modules/module.js";
```

Isso captura todas as exportações disponíveis no module.js e as torna disponíveis como membros de um objeto `Module`, efetivamente dando o seu próprio namespace. Então, por exemplo:

```js
Module.function1()
Module.function2()
etc.
```

Novamente, vejamos um exemplo real. Se você for ao nosso module-objects diretório, você verá o mesmo exemplo novamente, mas reescrito para aproveitar essa nova sintaxe. Nos módulos, as exportações são todas da seguinte forma simples:

```js
export { name, draw, reportArea, reportPerimeter };
```

As importações, por outro lado, são assim:

```js
import \* as Canvas from "./modules/canvas.js";

import \* as Square from "./modules/square.js";
import \* as Circle from "./modules/circle.js";
import \* as Triangle from "./modules/triangle.js";
```

Em cada caso, agora você pode acessar as importações do módulo abaixo do nome do objeto especificado, por exemplo:

```js
let square1 = Square.draw(myCanvas.ctx, 50, 50, 100, "blue");
Square.reportArea(square1.length, reportList);
Square.reportPerimeter(square1.length, reportList);
```

Agora você pode escrever o código da mesma forma que antes (contanto que inclua os nomes dos objetos quando necessário) e as importações sejam muito mais limpas.

Módulos e classes
-----------------

Como sugerimos anteriormente, você também pode exportar e importar classes; essa é outra opção para evitar conflitos no seu código e é especialmente útil se você já tiver o código do módulo gravado em um estilo orientado a objetos.

Você pode ver um exemplo do nosso módulo de desenho de forma reescrito com as classes ES em nosso classes diretório. Como exemplo, o `square.js` O arquivo agora contém todas as suas funcionalidades em uma única classe:

```js
class Square {
  constructor(ctx, listId, length, x, y, color) {
    ...
  }

  draw() {
    ...
  }

  ...
}
```

que exportamos então:

```js
export { Square };
```

No main.js, nós o importamos assim:

```js
import { Square } from "./modules/square.js";
```

E então use a classe para desenhar nosso quadrado:

```js
let square1 = new Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, "blue");
square1.draw();
square1.reportArea();
square1.reportPerimeter();
```

Módulos de agregação
--------------------

Haverá momentos em que você desejará agregar módulos. Você pode ter vários níveis de dependências, nos quais deseja simplificar as coisas, combinando vários submódulos em um módulo pai. Isso é possível usando a sintaxe de exportação dos seguintes formulários no módulo pai:

```js
export \* from "x.js";
export { name } from "x.js";
```

Por exemplo, veja nosso module-aggregation diretório. Neste exemplo (com base no exemplo de classes anteriores), temos um módulo extra chamado shapes.js, que agrega toda a funcionalidade de circle.js, square.js e triangle.js juntos. Também movemos nossos submódulos para dentro de um subdiretório dentro do diretório modules chamado shapes. Portanto, a estrutura do módulo neste exemplo é:
```

modules/
  canvas.js
  shapes.js
  shapes/
    circle.js
    square.js
    triangle.js
```

Em cada um dos submódulos, a exportação é da mesma forma, e.g.

```js
export { Square };
```

Em seguida, vem a parte de agregação. Dentro de shapes.js, incluímos as seguintes linhas:

```js
export { Square } from "./shapes/square.js";
export { Triangle } from "./shapes/triangle.js";
export { Circle } from "./shapes/circle.js";
```

Eles capturam as exportações dos submódulos individuais e os disponibilizam efetivamente no módulo shapes.js.

**Nota:** **Nota: As exportações mencionadas no shapes.js são basicamente redirecionadas pelo arquivo e realmente não existem nele, portanto, você não poderá escrever nenhum código relacionado útil dentro do mesmo arquivo.**

Portanto, agora no arquivo main.js., podemos obter acesso às três classes de módulos substituindo

```js
import { Square } from "./modules/square.js";
import { Circle } from "./modules/circle.js";
import { Triangle } from "./modules/triangle.js";
```

com a seguinte linha única:

```js
import { Square, Circle, Triangle } from "./modules/shapes.js";
```

Carregamento dinâmico do módulo
-------------------------------

A parte mais recente da funcionalidade dos módulos JavaScript a estar disponível nos navegadores é o carregamento dinâmico de módulos. Isso permite que você carregue módulos dinamicamente somente quando eles forem necessários, em vez de precisar carregar tudo antecipadamente. Isso tem algumas vantagens óbvias de desempenho; vamos ler e ver como isso funciona.

Essa nova funcionalidade permite que você ligue `import()` como uma função, passando o caminho para o módulo como um parâmetro. Retorna um`Promise`, que cumpre com um objeto de módulo (consulte Creating a module object) dando acesso às exportações desse objeto, e.g.

```js
import("./modules/myModule.js").then((module) => {
  // Do something with the module.
});
```

Vejamos um exemplo. No dynamic-module-imports diretório, temos outro exemplo baseado em nosso exemplo de classes. Desta vez, no entanto, não estamos desenhando nada na tela quando o exemplo é carregado. Em vez disso, incluímos trêsbuttons — "Circle", "Square", e "Triangle" — que, quando pressionado, carrega dinamicamente o módulo necessário e, em seguida, usa-o para desenhar os shape.

Neste exemplo, fizemos apenas alterações em nossa `index.html` e `main.js` arquivos - as exportações do módulo permanecem as mesmas de antes.

No main.js, pegamos uma referência a cada botão usando um`Document.querySelector()` chamada, por exemplo:

```js
let squareBtn = document.querySelector(".square");
```

Em seguida, anexamos um ouvinte de evento a cada botão para que, quando pressionado, o módulo relevante seja carregado dinamicamente e usado para desenhar a forma(shape):

```js
squareBtn.addEventListener("click", () => {
  import("./modules/square.js").then((Module) => {
    let square1 = new Module.Square(
      myCanvas.ctx,
      myCanvas.listId,
      50,
      50,
      100,
      "blue",
    );
    square1.draw();
    square1.reportArea();
    square1.reportPerimeter();
  });
});
```

Observe que, como o cumprimento da promessa retorna um objeto de módulo, a classe é então transformada em uma sub-característica do objeto, portanto, agora precisamos acessar o construtor com `Module.` anexado a ele, e.g. `Module.Square( ... )`.

Solução de problemas
--------------------

Aqui estão algumas dicas que podem ajudá-lo se você estiver com problemas para fazer seus módulos funcionarem. Sinta-se livre para adicionar à lista se descobrir mais!

* Mencionamos isso antes, mas para reiterar: arquivos`.js` precisa ser carregado com um tipo MIME de `text/javascript` (ou outro tipo MIME compatível com JavaScript, mas `text/javascript` é recomendável), caso contrário, você receberá um erro estrito de verificação do tipo MIME como "O servidor respondeu com um tipo MIME não JavaScript".
* Se você tentar carregar o arquivo HTML localmente (i.e. com um arquivo`://` URL), você encontrará erros do CORS devido a requisitos de segurança do módulo JavaScript. Você precisa fazer seus testes através de um servidor. As páginas do GitHub são ideais, pois também servem arquivos .js com o tipo MIME correto.
* Como .mjs é uma extensão de arquivo não padrão, alguns sistemas operacionais podem não reconhecê-lo ou tentar substituí-lo por outra. Por exemplo, descobrimos que o macOS estava adicionando silenciosamente .js ao final dos arquivos .mjs e ocultando automaticamente a extensão do arquivo. Então, todos os nossos arquivos foram lançados como x.mjs.js. Depois de desativarmos ocultar automaticamente as extensões de arquivo e treiná-lo para aceitar .mjs, tudo bem.
Veja também
-----------

* Using JavaScript modules on the web, por Addy Osmani e Mathias Bynens
* ES modules: A cartoon deep-dive, Postagem no blog Hacks por Lin Clark
* ES6 in Depth: Modules, Publicação de blog de Hacks por Jason Orendorff
* Livro de Axel Rauschmayer Exploring JS: Modules
* « Previous