# Introdução ao Javascript

## Visão Geral

Javascript (ou ECMAScript) é uma linguagem de programção muito utilizada no desenvolvimento Web. Com ela, é possível programar o comportamento das páginas HTML - alterar conteúdo e atributos HTML, CSS e mais.

O JavaScript nasceu como uma linguagem voltada para processamento no navegador. Entretanto, com a chegada do Node.js, que permite a execução de Javascript fora do navegador, *back-ends* de websites e aplicações feitas majoritariamente em Javascript (como o Discord) também passaram a utilizar amplamente a linguagem.

Praticamente todas as páginas na internet usam Javascript para fazer operações *client-side*, como verificação de campos, envio de formulários, gerenciamento de cookies, solicitações de informações para o servidor etc.

```markup
<!DOCTYPE html>
<html>
    <body>
        <p id="teste">JavaScript pode mudar conteúdo HTML </p>
        <button type="button" onclick='document.getElementById("teste").innerHTML = "Viu? Modificado!"'> Ao clicar aqui, o texto do parágrafo irá mudar! </button>
    </body>
</html>
```

### Engines

Uma Engine Javascript ou Interpretador Javascript é um programa especializado em ler e processar código Javascript, todos os mais populares navegadores modernos utilizam interpretadores mas a engine especifica depende de qual navegador está sendo utilizadas, sendo possivel que diferentes interpretadores entendam código de formas diferentes. Alguns exemplos de engines e navegadores diferentes são:

| Engine                                                                 | Navegador             |
| ---------------------------------------------------------------------- | --------------------- |
| \[V8]\(<https://en.wikipedia.org/wiki/V8_(JavaScript_engine>))         | Google Chrome e Opera |
| [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey)             | FireFox               |
| \[Chakra]\(<https://en.wikipedia.org/wiki/Chakra_(JavaScript_engine>)) | Internet Explorer     |
| [WebKit](https://en.wikipedia.org/wiki/WebKit)                         | Safari                |

Por consequência é importante sempre verificar quais features são tem suporte em quais engines, para isso você pode verificar em tabelas de compatibilidade:

* <https://caniuse.com/>
* <https://kangax.github.io/compat-table/es6/>

É importante lembrar que mesmo navegadores sendo o principal uso de Engines qualquer software que precisa processar Javascript utiliza uma engine de forma ou outra.

## Estrutura e sintaxe do JS

### Script interno e externo

O código Javascript pode estar dentro ou fora de um documento HTML. Em ambos os casos, o Javascript fica dentro de uma tag `<script></script>`.

* Externo:

  ```markup
  <!DOCTYPE html>
  <html>
    <head>
        <script src="/caminho/ate/arquivo/myScript.js"></script>
        <script src="https://www.sitecomscripttop.com/myScript.js"></script>
    </head>
    <body>
        <h1> Olá </h1>
    </body>
  </html>
  ```
* Interno (no HEAD):

  ```markup
  <!DOCTYPE html>
  <html>
    <head>
        <script>
            function myFunction() {
              document.getElementById("para1").innerHTML = "Parágrafo modificado";
            }
        </script>
    </head>
    <body>
        <h1> Página de teste </h1>
        <p id="para1"> Um parágrafo </p>
        <button type="button" onclick="myFunction()"> Mudar parágrafo </button>
    </body>
  </html>
  ```

### Comentários

Você pode adicionar comentários no seu código para mante-lo organizado sem afetar a execução, comentários são linhas de codigo que são ignoradas pelo interpretador.

* Utilizando duas barras você comenta até o fim da linha

```javascript
// Essa linha está comentada

let variavel = "valor"; // Metade da linha está comentada
```

* Utilizando uma barra e um asterisco você pode comentar multiplas linhas de código

```javascript
/* 
  Esse é um comentário multilinha
  Tudo aqui está comentado
*/
```

### Variáveis e constantes

**Variáveis** são usadas para armazenar dados que podem ser modificados a qualquer momento. Em JS, as variáveis são declaradas com `var` ou `let`e elas podem ser praticamente qualquer coisa: números, palavras, funções etc.

Ao usar `var`, se a variável for declarada fora de uma função, ela poderá ser acessada de qualquer ponto do código (dentro e fora de funções), ou seja, ela é de *scope* global. Caso a variável seja declarada dentro de uma função, ela só poderá ser acessada de dentro dessa função. Esse tipo de variável pode ser redeclarado - além de atualizado - no meio do código.

```javascript
    var msg_introdutoria = 0.5; // declara a variável e atribui um real (float) a ela
    var msg_introdutoria = "Olá mundo!"; // redeclara a variável e atribui uma string a ela
    var contador = 0; // declara uma variável e atribui um inteiro (int) a ela

    console.log(msg_introdutoria); // exibirá "Olá mundo!"

    if (contador <= 0) {
        // bloco de código do IF
        var msg_introdutoria = "Oi mundo!";  // atualiza o valor da variável
    }

    console.log(msg_introdutoria) // exibirá "Oi mundo!"
```

Já ao usar `let`, a variável sempre será *block scoped*, ou seja, ela está limitada ao bloco de código em que foi declarada (e aos blocos mais internos a ela). Um bloco é definido por chaves (`fora do bloco { dentro do bloco } fora do bloco`). Além disso, variáveis declaradas com *let* não podem ser redeclaradas (mas podem ser atualizadas).

```javascript
    let msg_introdutoria = "Olá mundo!";
    let contador = 4;

   if (contador > 3) {
        let msg_introdutoria_2 = "Oi mundo!";

        console.log(msg_introdutoria); // "Olá mundo!"
        console.log(msg_introdutoria_2); // "Oi mundo!"
    }
    console.log(msg_introdutoria); // "Olá mundo!"
    console.log(msg_introdutoria_2); // msg_introdutoria_2 não está definida
```

**Constantes** também são usadas para armazenar dados, mas elas não podem ser modificadas durante a execução do programa. Uma vez declaradas com certo valor, elas não podem ser alteradas. Além disso, constantes são *block scoped* e não podem ser redeclaradas (nem alteradas - como foi dito logo acima).

```javascript
    const saudacao = "Olá!";
    saudacao = "Oi!"; // Erro: (re)atribuição à constante

    // OBS.: se a constante for um objeto é possível fazer certas alterações:
    const saudacao2 = { // objeto com mais de um campo
        msg : "Olá!",
        countador : 3
    };

    saudacao2.msg = "Oi!"; // Isso é permitido! O campo msg é atualizado!

    const saudacao2 = {
        teste : "Aaaa",
        nome : "Marcelo Batata"
    }; // isso não é permitido! ERRO!!
```

### Operadores e comparadores

* **Operadores aritméticos**: são os operadores que realizam operações aritméticas em números (e variáveis com valores numéricos). Entretanto, em certos casos, é possível usar esses operadores com outros tipos de variáveis, como no caso de "soma" de strings (`"Nome " + "Sobrenome" -> "Nome Sobrenome"`).

| Operador aritmético |     Operação    |             Exemplo            |
| :-----------------: | :-------------: | :----------------------------: |
|          +          |      Adição     |    `let x = 1 + 2; // x = 3`   |
|          -          |    Subtração    |   `let x = 5 - 7; // x = -2`   |
|          \*         |  Multiplicação  | `let x = 3 * 5.2; // x = 15.6` |
|          /          |     Divisão     |    `let x = 6 / 2; // x = 3`   |
|         \*\*        |   Pontenciação  |    `let x = 2**3; // x = 8`    |
|          %          |  Módulo (resto) |   `let x = 10 % 3; // x = 1`   |
|          ++         | Incremento (+1) |   `let x = 1; x++; // x = 2`   |
|          --         | Decremento (-1) |   `let x = 1/ x--; // x = 0`   |

> **Operações matematicas são "seguras" no JavaScript** isso significa que você pode fazer qualquer conta e não vai gerar um erro fatal que mata o programa, no máximo retornando *NaN* (Not-a-Number), um valor númerico que não existe.

* **Comparadores**:

| Comparador |                  Compração                 |       Exemplo       |
| :--------: | :----------------------------------------: | :-----------------: |
|     ==     |             Igual a (em valor)             |  `1 == 1.0 (true)`  |
|     ===    |          Igual a (em valor e tipo)         | `1 === 1.0 (false)` |
|     !=     |         Diferente de ("não igual")         |  `1 != 1.0 (false)` |
|    !===    | Diferente de ("não igual" em valor e tipo) |  `1 !== 1.0 (true)` |
|      >     |                  Maior que                 |   `10 > 2 (true)`   |
|      <     |                  Menor que                 |    `1 < 2 (true)`   |
|     >=     |             Maior ou igual que             |   `5 >= 5 (true)`   |
|     <=     |             Menor ou igual que             |   `4 <= 3 (false)`  |

* Ainda há os **comparadores lógicos**. São eles:
  * `&&` (and): `(2 < 10 && 0 > 1)` --> verdade **E** mentira é **mentira**
  * `||` (or): `(5 == 5 || 3 == 5)` --> verdade **OU** mentira é **verdade**
  * `!` (not): `!(1 == 1)` --> **NÃO** verdade é **mentira**
* E, por último, também é importante conhecer o **comparador ternário**, que atua como um comparador IF:

```javascript
// Comparador ternário: 
// variablename = (condition) ? value1 : value2;
var voteable = (age < 18) ? "Too young" : "Old enough";

// Isso é igual a:
if (age < 18) {
  voteable = "Too young";
} else {
  voteable = "Old Enough";
}
```

### Tipos de dados

De forma simplificada, podemos resumir os tipos de dados em primitivos e complexos. Os **tipos primitivos** são:

* *string* (basicamente, caractéres e palavras - sempre entre aspas).
* *boolean* (verdadeiro ou falso).
* *number* (número inteiro, real).
* *undefined* (variáveis sem valor definido).

Já os **tipos complexos** são:

* *object* (listas, JSON, XML, vetores, dados inexistentes etc.).
* *function* (funções).

```javascript
typeof "" // String
typeof "Marcelo Batata" // String

typeof 3 // Number
typeof 3.14 // Number
typeof (3 + 4) // Number

var x; // Declarada, mas sem valor atribuído
typeof x // Undefined

typeof true // Boolean
typeof false // Boolean

typeof { name:'John', age:34 } // Object
typeof [1, 2, 3, 4] // Object
typeof null // Object

typeof function myFunc(){ console.log("Testing..."); } // Function
```

Obs.: Ainda há **null**, que é similar ao *undefined*, mas seu tipo é objeto, Por mais contraditório que isso seja, esse objeto *null* represta um dado que não existe.

```javascript
typeof undefined // retorna undefined
typeof null // retorna object

null === undefined // retorna false
null == undefined // retorna true (loose comparison)
```

### Funções

Funções são blocos de códigos que executam uma tarefa. Algo deve invocar a função para ela ser executada (ela precisa de algum "gatilho", nem que seja outra parte do código "chamando" ela - ou até ela própria se invocando). Ou seja, a execução do código dentro da função ocorre quando:

* Um evento ocorre (ex.: usuário pressiona um botão);
* A função é invocada por outro trecho de código Javascript;
* A própria função invoca-se e é executada automaticamente.

#### Sintaxe

```javascript
function nome_funcao(parametro1, parametro2, parametro3) {
  // código a ser executado quando a função for chamada
  console.log("A função foi executada!");

  return {"mensagem" : "OK"};
}

// --- Outra alternativa, em certos casos, é a "Arrow Function": ---
// O trecho abaixo pode ser escrito de forma mais concisa
var multiplicacao = function(x, y) {
  return x * y;
};
// Arrow function: (param1, param2, paramN) => { expressão / bloco da função }
const multiplicacao2 = (x, y) => { return x * y };
```

### Exemplo comentado

Para ajudar no entendimento da sintaxe da linguagem é bom analisar um trecho de código comentado.

```javascript
// o bloco de código da função 'requisitarDadosPessoais()' começa aqui e quando ela for chamada, tudo que está aqui dentro será executado (linha por linha, de cima para baixo)
// userID é um parâmetro que deve ser passado ao chamar essa função. userId funciona como uma varíavel
async function requisitarDadosPessoais(userID) { 
    // a variável 'dados' recebe o retorno da função 'httprequest', ou seja, o que essa função trouxer como resposta sera guardado em 'dados'
    var dados = await httprequest(`http://site-exemplo.com/usuarios/${userID}`); // a função é executada e em seguida sua resposta é armazenada em 'dados'

    if (!dados) { // se 'dados' estiver vazio (for nulo), a condição é verdade e o código dentro desse bloco (delimitado por chaves) é executado
        alert(`O usuário ${userID} não existe!`); // emite um alerta na tela avisando que o usuário com o nome armazenado em 'userID' não existe
        return null; // a função 'requisitarDadosPessoais()' termina aqui e retorna o valor 'null' (nulo)
    } // fim do bloco de código referente ao 'if'

    if (dados.sucesso == true){ // 'dados' é um objeto com vários campos (atua como um JSON) e ele tem um parâmetro 'sucesso'. Se 'sucesso' for igual 'true', a condição é satisfeita e o código dentro desse bloco é executado
        alert(`Bem vindo, ${dados.nome}, faz ${dados.tempoDesdeUltimoLogin} horas que você conectou pela última vez`); // emite uma mensagem de boas-vindas na tela, fazendo uso de outros parâmetros dentro de 'dados' ('nome' e 'tempoDesdeUltimoLogin')
        redirecionar_usuario('http://site-exemplo.com/profile/${userID}', dados.cookies); // Executado uma função chamada 'redirecionar_usuario()' que está em outra parte do arquivo Javascript
    } // fim do bloco de código referente ao 'if'
    else { // caso a condição nos parênteses do 'if' não seja satisfeita, esse bloco de código é executado
        alert(`${dados.nome}, a senha digitada está incorreta`); // emite um alerta na tela, avisando que a senha referente ao usuário digitado está incorreta
    } // fim do bloco de código referente ao 'else'

    return dados; // caso a função não tenha terminado antes, ela termina aqui, retornando o conteúdo de 'dados' (variável) para onde foi feita a chamada à essa função
}
```

## Leitura adicional

* Guias detalhados do JavaScript básico ao avançado
* [Manual - Javascript](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference)
* [Especificação do JavaScript](https://www.ecma-international.org/publications-and-standards/standards/ecma-262/)
