Desenvolvimento Web Completo 2020 - 20 cursos + 20 projetos

Seção 8 - Javascript

Aula 145 - O que é Javascript
Javascript é uma linguagem de alto nível. Pode ser utilizada no client-side e no server-side, bem como para aplicações desktop com o Electron ou mobile com o React Native.
No client-side permite aplicar dinâmica aos elementos da página web.
Aula 146 - Antes de iniciarmos aqui vai uma dica
Dicas sobre ferramentas do desenvolvedor.
Aula 147 - Incluindo JavaScript em páginas HTML5 parte 1 - Introdução e preparação
Podemos incluir código Javascript no HTML de duas formas:
Diretamente no arquivo HTML dentro da tag <script>.
A partir de um arquivo externo importado com a tag <script src="meu_arquivo.js>.
Em aplicações HTML4 devemos incluir o atributo type="text/javascript". Em aplicações mais antigas podemos encontrar a instrução <script language="javascript">.
Aula 148 - Incluindo JavaScript em páginas HTML5 parte 2 - Local e Externo
Podemos incluir as tags de <script> tanto no final da estrutura <head> como no final da <body>. A diferença dessas abordagens está no momento da interpretação do código e pode gerar um erro de precedencia de interpretação.
Aula 149 - Incluindo JavaScript em páginas HTML5 parte 3 - Precedência de execução
Em alguns momentos o Javascript pode depender que algum elemento html esteja carregado antes de sua execução. Por isso é importante saber em que momento o script será carregado.
Como exemplo criamos um <input> que será modificado através do Javascript com a instrução document.getElementById('nome').value = 'Oi'.
Se invocarmos o script dentro do <head> nada vai ocorrer pois ele será executado antes da interpretação do html. Podemos verificar esse erro também no console que exibe uma mansagem de erro (Cannot set property 'value' of null).
Esse erro de precedência é corrigido colocando a execução do Javascript no final do <body>.
Aula 150 - Comentários
Como fazer comentários no Javascript. (// uma linha, ou /* */ múltiplas linhas).
Aula 151 - Variáveis - Introdução
Variáveis são espaços de memória que permitem armazenar dados de forma temporária.
Tipos principais de variáveis em Javascript: string, number e boolean
Regras de sintaxe para nomes de variáveis: Não podem ser iniciadas por números, não podem utilizar caracteres especiais (ç, ^, ~) e não podem ser utilizadas palavras reservadas, são case sensitive.
Aula 152 - Variáveis - Prática
Criação de vários tipos de variáveis com o comando var
Lembre que o Javascript assume o tipo de variável pelo valor atribuido a ela.
Utilizando comandos de retorno:
alert() - abre um dialog.
document.write() - escreve o valor no browser.
console.log() - exibe o valor no console do browser.
Aula 153 - Concatenação
Podemos concatenar textos com srtings utilizando o operador '+'.
Quando a concatenação é com variáveis tipo numerica o Javascript já percebe que o operador '+' não é para uma soma e tranforma a variável, se for numérica, em string.
Em seguida atribuimos às variáveis valores obtidos do usuário com o comando prompt(). O prompt() sempre recebe os valores como string, mesmo que sejam numeros.
Aula 154 - Usar ou não o ';' no final dos comandos?
A utilização ou não do ';' nos códigos Javascript é opcional não alterando o resultado do programa.
Aula 155 - Variáveis null e undefined
Os valores null e undefined são valores primitivos do Javascript. A diferença entre eles é que o null representa a ausencia intencional de um valor. Já a undefined significa que não existe um valor para a variável, ou seja ela é indefinida ou inexistente.
Poderemo notar a diferença entre elas nas expressões condicionais e no retorno de funções.
Aula 156 - Alterando valores de variáveis
Podemos alterar o valor de variáveis apenas reatribuindo novos valores para a variável. O Javascript altera também o tipo da variável de acordo com o valor atribuido.
Aula 157 - Revisão e desafio A-B-C
Podemos alterar o valor de variáveis apenas reatribuindo novos valores para a variável. O Javascript altera também o tipo da variável de acordo com o valor atribuido.
Aula 158 - If/else parte 1 - Introdução
Explicações sobre os comandos:
if(condição){código a ser executado} else{código a ser executado} ou
if(condição){código a ser executado} else if(condição){código a ser executado} else{código a ser executado}
Aula 159 - Operadores de comparação (condicionais)
Operadores condicionais: (também conhecidos como operadores relacionais).
== Igual: Verifica se os valores comparados são iguais.
=== Idêntico: verifica se os valores comparados são iguais e do mensmo tipo.
!= Diferente: Verifica se os valores comparados são diferentes.
!== Não idêntico: verifica se os valores comparados são diferentes e de tipos diferentes.
<, <= Menor / menor ou igual: Verifica se o valor da esquerda é menor/menor ou igual ao valor da direita.
>, >= Maior / maior ou igual: Verifica se o valor da esquerda é maior/maior ou igual ao valor da direita.
Aula 160 - If/else parte 2 - Praticando com operadores de comparação
Testando o if/else com os diversos operadores condicionais.
Aula 161 - Praticando um pouco mais com operadores de comparação
Realizando uma operação de teste de nota (aprovado / reprovado).
Para esse exercício utilizamos o prompt() para receber os dados. O prompt() recebe os dados como string asssim o Javascript faz as principais condicionais sem levar em consideração o tipo. A excessão é com as condicionais === e !==.
Aula 162 - Casting de tipos com toString(), parseInt() e parseFloat()
Casting de tipos é converter um tipo de dado em um tipo diferente. Lembrando que o Javascript é fracamente tipada ou seja as variáveis recebem o seu tipo no momento da declaração e podem ter seu tipo alterado durante a execução do programa.
Aula 163 - Operadores lógicos
Operadores lógicos:
&& E(and): Verdadeiro se todas as expressões forem verdadeiras.
|| Ou(or): Verdadeiro se pelo menos uma das expressões for verdadeira.
! Negação(not): Inverte o resultado de comparação.
Aula 164 - If/else parte 3 - Praticando com operadores lógicos
Fazendo testes com operadores condicionais e operadores lógicos
Aula 165 - Operador ternário
O operador ternário faz a mesma função do if/else com uma sintaxe mais enxuta. A sintaxe para o operador ternário é: br condição ? resultado se verdadeiro : resultado se falso.
O resultado da condição tem que ser um valor e não pode ser uma expressão ou outro teste lógico, diferente do if/else.
Aula 166 - Atividades para fixação do conteúdo
Atividade com comandos if/else aninhados.
Aula 167 - Switch
Condicional switch sintaxe:
switch(opção) {
case parâmetro 1:
//código a ser executado
break
case parâmetro 2:
//código a ser executado
break
default:
//código a ser executado
break
}
Aula 168 - Switch na prática
Criação de uma estrutura condicional switch.
Lembre que os parâmetros no case não aceitam testes lógicos ou outras operações, apenas valores para comparação/verificação.
Outra questão é que o switch faz a verificação de valor e tipo, portanto a comparação é de valores identicos, assim quando pegamos o valor do prompt() por exemplo precisamos converter o valor recebido caso desejemos comparar com numeros.
Aula 169 - Operadores aritméticos
Operadores:
+ : soma de valores (atenção para casos de concatenação)
- : subtração
* : multiplicação
/ : divisão
% : módulo (resto de divisão)
++ : pré/pós incremento
-- : pré/pós decremento
Aula 170 - Praticando com operadores aritméticos
Realizando cálculos com os operadores aritméticos.
Atenção aos casos de pré incremento/decremento e pós incremento/decremento.
Devemos sempre nos atentar ao tipo dos valores que chegarão nas variáveis, pois na maioria das vezes os valores não vem como numero mais sim como string. Esse problema é mais comum nas operações de soma pois o operador + pode realizar uma concatenação.
Note que no exemplo foi feita a conversão de string para Int apenas na operação de soma (não fiz a conversão globalmente para ficar claro que o Javascript faz a conversão automaticamente nas outras operações).
Aula 171 - Operações aritméticas na atribuição de valores
Utilizando as atribuição com operação ( +=, -=, *=, /= e %= ) para números e para concatenção de strings ( += )
Aula 172 - Precedência de execução das operações aritméticas
Analisando a precendencia de operadores aritméticos:
1o. multiplicação e divisão
2o. soma e substração
Aula 173 - Atividades para fixação do conteúdo./images/uc05/Aula_173.png
Atividade com if/else e operadores aritméticos (cálculo do IMC).
Aula 174 - Funções
Encapsular um bloco de códigos com um objetivo definido.
function calcularAreaTerreno(largura, comprimento) {
var area = largura * comprimento
return area
Padrões para nomes de funções ( verbo_no_infinitivoSubstantivo ).
Parâmetros ou argumentos funcionam como uma entrada de dados para a função. Podemos passar nenhum parâmetro ou vários parâmetros.
Dentro do escopo da função podemos criar variáveis, criar estruturas de repetição, estruturas condicionais e inclusive chamar outras funções.
As funções podem ser do tipo void (não retornam nenhum valor apenas processam alguma lógica) ou com retorno quando processada vai retornar um valor para o script que a invocou.
Aula 175 - Funções - prática
Iniciamos a criação de uma função. O nome da função, bem como dos parâmetros deve seguir a mesma sintaxe que para variáveis.
Após criarmos a função devemos desenvolver a lógica utilizada por ela.
Feita a lógica podemos invocar essa função em nosso código. Quando chamamos uma função que espera algum parâmetro devemos encaminhar esses parâmetros na ordem definida na função.
Funções void realizam um processamento mas não retornam nada para quem fez a chamada. Já as funções do tipo retorno, retornam um parametro para quem realizou a chamada.
Mesmmo que façamos uma saida para a função (por exemplo com document.write()) se ela não tiver um return ela será do tipo void, mesmo apresentando o resultado na tela. Com isso a função se torna restrita àquele tipo de operação, e sua execução se limita aquele tipo de saida.
Para utilizarmos uma função em diversos momentos diferentes utilizamos o return. Com o return podemos enviar qualquer valor, seja uma string, um numero, um boolean ou uma variável. Esse retorno pode ser tratado posteriormente por quem chamou a função.
Podemos também atribuir o retorno da função a uma variável. Para isso chamamos a função no valor de atribuição da variável. Note que podemos declarar a variável externa com o mesmo nome da variável interna da função. Isso devido a diferença de escopo das duas.
Outro detalhe é que quando fazemos a função do tipo void com uma saida para a tela, toda vez que chamarmops a função ela fará o retorno na tela (note como ficou o exemplo).
Podemos passar os parametros para a função de diversas formas.
Em Javascript podemos declarar a função mesmo após sua chamada pois o Javascript faz toda a leitura do script antes de comçar a sua execução, portanto antes da execução pelo interpretador ele já aloca a posição da função na memória.
Aula 176 - Funções - Flexibilidade de parâmetros
O Javascript, diferente de outras linguagens permite que passemos diferentes quantidades de parâmetros independente de quantos foram declarados na construção da função. Isso não quer dizer que ele executará todos os parâmetros, mas sim que ele não vai dar erro.
Por exemplo se declaramos em uma função dois parâmetros e passamos na chamada quatro parâmetros, o Javascript simplesmente vai ignorar os dois últimos. Lembrando que podemos declarar na função quantos parâmetros forem necessários.
Já se passamos menos parametros que o declarado, os parametros faltantes serão considerados como undefined. Nesse caso em uma soma, por exemplo, o resultado será NaN(not a number).
Nos casos em que podemos ter parâmetro a menos que o necessário, como o parâmetro faltante é cconsideredo como undefined, podemos tratar esse falta, como no exemplo
b = b === undefined ? 0 : b; (se b for undefined atribua o valor 0, se não b vale b).
O mesmo ocorre quando não passamos nenhum parâmetro. Neste caso todos os parâmetros serão considerados undefined.
Por fim podemos passar parâmetros variáveis (quantidade indefinida) mas para isso precisamos de arrays e loops.
Aula 177 - Escopo de variáveis
O Javascript possui 3 escopos de variáveis: global, função e bloco.
O escopo global se refere a função como um todo.
O escopo de função correponde ao conteúdo dentro do bloco da função.
O escopo de bloco corresponde a instruções contidas dentro de comandos como o if e o while.
Quando declaramos uma variável no escopo global podemos acessá-la no escopo de bloco e no escopo de função.
Quando declaramos uma variável em um bloco com o comando 'var' temos o hoisting dessa variável, ou seja, ela é elevada ao escopo global, sendo acessível tanto no script quanto nas funções.
Já variáveis declaradas no escopo da função não sofrem a elevação e ficam restritas ao escopo da função.
Quando um bloco está dentro de uma função, a variável declarada nele também sofrerá o hoisting mas apenas do escopo de bloco para o escopo da função em que o bloco está declarado. Neste caso a variável não se eleva para o escopo global.
Aula 178 - Funções anonimas e a técnica de wrapper
Funções anonimas são ideais para serem utilizadas como parametros de callback de outras funções.
Funções anonimas são funções sem nome definido. Para isso utilizamos o conceito de wrapper. No Javascript podemos atribuir às variáveis não apenas valores mas também funções. Utilizando esse conceito podemos atribuir ao valor de uma variável uma função anonima que será chamada pelo nome da variável seguida de ().
Esse recurso é muito utilizado em Javascript pois utiliza-se muito as funções de callback que são funções chamadas como parametro em outras funções.
Aula 179 - Funções de callback
Funções de callback são funções passadas como parâmetro para outras funções. Esse tipo de fuhnção é muito comum em lógicas com processamento assíncrono.
Quando criamos uma função que tem que executar outra lógica, ou seja, uma outra função nos parâmetros podemos, por exemplo, incluir essa funções como parâmetro na chamada da função principal desse modo:

funçãoPrincipal(parametro1, function(){ ... }, function(){ ... })

Entretanto dessa forma teremos dificuldade em fazer as manutenções no código, além de não podermos reaproveitar a função.
Então o correto é criarmos as funções que serão parâmetro para a função principal utilizando as funções anonimas e chama-las apenas como parametro da função principal dessa forma:

var funcao1 = function(){ ... }
var funcao2 = function(){ ... }
funçãoPrincipal(parametro1, funcao1, funcao2)

Quando chamamos uma função anonima como parâmetro em outra função não devemos utilizar parenteses pois caso contrário o Javascript vai entender que deve executar a função no momento que ela for lida nos parâmetros quando o que se espera é apenas encaminhar essa função.
Aula 180 - Funções nativas para manipular strings
Estudar os principais atributos e métodos nativos para objetos strings. Mais informações em: W3Schools - JavaScript String Reference
Propriedades e métodos:
legth : mostra a quantidade de caracteres da string.
charAt() : exibe o caracter na posição solicitada (índices iniciam em 0).
indexOf(): exibe o índice do primeiro caracter pesquisado. Este método é case-sensitive. Caso não encontre o valor o retorno será sempre '-1'.
replace(): substitui os caracters selecionados por outro valor.
substr: extrai parte da string a partir da posição selecionada, com a quantidade de caracteres selecionada.
toLowerCase() : converte a string para caixa-baixa.
toUpperCase() : converte a string para caixa-alta.
trim(): remove espaços em branco no inpicio e no final da string.
Aula 181 - Funções nativas para tarefas matemáticas
Estudar os principais atributos e métodos nativos para objetos matemáticos. Mais informações em: W3Schools - JavaScript Math Reference
Propriedades e métodos:
Math.ceil() : arredonda o numero sempre para cima.
Math.floor() : arredonda o numero sempre para baixo.
Math.round() : arredonda o numero pela média.
Math.random() : gera numeros flutuantes aleatórios entre 0 e 1
Aula 182 - Funções nativas para manipular datas
Estudar os principais atributos e métodos para manipulação de datas. Mais informações em: W3Schools - JavaScript Date Reference
Diferente dos métodos Math para utilizar os métodos de data devemos instanciá-lo conforme segue:

var data = new Date()

Com isso passamos a ter um novo objeto de data atribuido a uma variável que terá as informações do momento que for instanciado. Os valores de data são obtidos de acordo com a configuração da máquina do usuário, portanto refletem o valor que estiver configurado na máquina naquele momento.
Geralmente as datas são trabalhadas no back-end, entretanto podemos trabalhar no front-end com esse objeto.
Propriedades e métodos:
getDate() : exibe o dia do mes.
getMonth() : exibe o mes (a contagem é feita de 0 a 11, assim precisamos somar 1 para ter o número do mes correto).
getFullYear : exibe o ano.
Os métodos de data além de apresentarem o tempo atual permitem que façamos a atribuição de uma data com os métodos set.
Aula 183 - Praticando um pouco mais com datas
Continuando as operações com datas:
toString() : exibe a data completa (dia da semana, mes, dia do mes, ano, hora, fuso horário).
setDate() : seta o dia do mes através de soma ou subtração de dias.
setMonth() : seta o mes através de soma ou subtração de meses.
setFullYear() : seta o ano através de soma ou subtração de anos.
Podemos setar a data desejada quando instaciamos a data com o comando:

var data = new Date(ano, mes(-1), dia, hora, min, seg, ms)

Para fazer cálculos com datas transformamos a data com o método: getTime() : converte a data em um numero real em milissegundos calculada a partir de 01/01/1970.
Neste exemplo utilizamos mais uma propriedade matemática a Math.abs() que converte qualquer numero em número positivo.
Por fim precisamos fazer os cálculos matemáticos para converter a unidade de tempo que se deseja encontar para milissegundos.
Aula 184 - Atividades para fixação do conteúdo
Criação de uma aplicação de cáculo de soma e subtração. Na minha resolução utilizei funções anonimas de callback para selecionar o tipo de operação ou enviar uma mensagem de erro caso a digitação for inválida.
Aula 185 - Eventos parte 1 - Introdução
Eventos nos possibilitam capturar ações ocorridas dentro do browser como o movimento do mouse, o toque do teclado, o redimensionamento da página entre outros. Esse eventos podem ser combinados com funções para executar lógicas.
Aula 186 - Eventos parte 2 - Mouse
Principais eventos de mouse:
onclick : acionado quando o evento é clicado.
ondblclick : acionado quando o evento é clicado duas vezes.
onmouseup : acionado quando o clique sobre o elemento é liberado.
onmouseover : acionado quando o cursor está sobre o elemento.
onmouseout : acionado quando o cursor do mouse sai da área ocupada pelo elemento.
Podemos utilizar os eventos diretamente nas tags dos elementos que serão ativados pelo evento. Isso pode ser feito incluindo o evento como uma propriedade na tag como no exemplo:

<div onclick="alert('teste')"></div>

O mais usula entretanto é passar funções para a execução das tarefas do seguinte modo:

<div onclick="funcao()"></div>

Podemos também combinar vários eventos em um mesmo elemento.
Nem todos os eventos estão diponíveis para todas as tags. Consultar a documentação na W3schools DOM Events em Technical Details
Aula 187 - Eventos parte 3 - Teclado
Principais eventos de teclado:
onkeydown : acionado quando uma tecla é pressionada.
onkeypress : acionado entre o keydown e o keyup ou seja quando mantem a tecla pressionada (somente quando a tecla for um caractere, não conta para teclas especiais como CTRL ).
onkeyup : acionado quando quando uma tecla é liberada.
Quando utilizamos o onkeydown o evento é disparado (no nosso exemplo um alert) e o resultado da tecla pressionada só vai ocorrer depois do evento(no caso como é um alert, somente após fecharmos o alert). Essa característica é importante para a verificação de máscaras de caracteres pois podemos bloquear a digitação de caracteres inválidos antes de eles aparecerem no campo do formulário.
O onkeypress é muito semelhante ao onkeydown. A principal diferença é, como mencionado com as teclas especiais (CTRL, ALT, SHIFT) que são ignoradas no onkeypress
Aula 188 - Eventos parte 4 - Janela
Principais eventos de janela(frame):
onresize : acionado quando o frame ou a página é redimensionada.
onscroll : acionado quando o scroll do mouse é acionado.
O evento onresize por agir na janela como um todo é um evento típico da tag <body>.
Já o evento onscroll pode ser atribuido ao elemento que é passível de rolagem, inclusive o <body>.
Aula 189 - Eventos parte 5 - Formulários
Principais eventos de Formulário:
onfocus : acionado quando clicamos no elemeto colocando o foco nele.
onblur : acionado quando o elemento perde o foco, ou seja, quando mudamos de campo no formulário.
onchange : acionado quando o estado do elemento é alterado, principalmente em elementos do tipo select.
O evento onresize por agir na janela como um todo é um evento típico da tag <body>.
Já o evento onscroll pode ser atribuido ao elemento que é passível de rolagem, inclusive o <body>.
Aula 190 - DOM parte 1 - Introdução
O DOM é uma API multiplataforma que permite o acesso através do Javascript a todos os elementos que fazem parte de nossa página. Com ele conseguimos acessar e modificar todos os elementos que compõem nossa página.
Todos os elementos do HTML ficam organizados em um objeto document sendo que essa organização pode ser representada como uma árvore onde os elementos pais encapsulam os elementos filhos formando trajetos definidos em todos os elementos que compõe a página.
Cada elemento HTML contido no DOM é chamado de node(nó).
Aula 191 - DOM parte 2 - Selecionando elementos da página
Para selecionar elementos no DOM temos alguns métodos da API do DOM acesssíveis a partir do objeto document:
getElementById() : Seleciona o elemento pela sua id. É o método mais utilizado em Javascript para sseleções no DOM e por esse motivo as ids devem ter nomes únicos.
getElementsByTagName() : Seleciona os elementos pela tag
getElementsByClassName() : seleciona os elementos pela classe
getElementsByName() : seleciona os elementos pelo name
Podemos selecionar os elementos por seus atributos.
Note que o getElementById() é o único que tem o seu nome no singular. Isso porque espera-se que a id seja realmente única.
Quando utilizamos o getElementById() o retorno é o elemento pois ele é único.
Já quando utilizamos o getElementsByClassName() ou o getElementsByTagName() temos uma HTMLCollection pois podemos ter vários resultados para essa seleção. Essa collection é apresentada em forma de array.
O getElementsByName() por sua vez retorna um NodeList também em forma de array.
Aula 192 - DOM parte 3 - Manipulando valores de inputs (text)
Aqui fizemos uma pequena lógica para separarmos os caracteres digitados em letras e numeros.
Para isso utilizamos o método getElementById() para 'escutar' a propriedade value do <input> e armazenar o valor em uma variável.
O valor dessa variável é testado e caso retorne um número é atribuido ao <input> de números e caso retorne uma letra é atribuido ao <input> de letras ambos também com o método getElementById().value só que desta vez com o operador de atribuição (no caso o de concatenação e atribuição '+=').
Na lógica de teste para números e letras, fiz de forma diferente. No exemplo foi utilizado o switch, mas eu fiz a lógica com if e parseInt().
Aula 193 - DOM parte 4 - Manipulando estilos de elementos
Nesta aula utilizamos três botões para alterar a cor de fundo de um elemento criado em uma <div>. Os botões são monitorados pelo evento onclick e executam uma função passando como parâmetro a cor desejada.
Ess função seleciona o elemento utilizando o método getElementById() e alterando a propriedade style.background atribuindo o valor recebido a essa propriedade.
Podemos ver os estilos que podem ser manipulados em HTML DOM Style Object
Alteramos tabém as propriedades height e width, passando seus valores também por parâmetro.
Note que como não passamos o valor do width nos parâmetros da cor vermelha o quadrado assume o último valor atribuido a sua largura.
Aula 194 - DOM parte 5 - Manipulando classes de elementos
Nesta aula modificamos a classe de um elemento utilizando o método getElementById e a propriedade className. Com isso podemos mudar os estilos do elemento através de opções do CSS.
Aula 195 - Atividades para fixação do conteúdo
Criação de uma aplicação que muda a cor de fundo de um campo <input> de acordo com a quantidade de caracteres digitados.
Minha execução utilizou o mesmo método do gabarito, porém considerou a opção de não ter caracteres (volta para transparent).
Aula 196 - App Calculadora parte 1 - Criando a função calcular
Inicio da criação de uma calculadora. A base da calculadora já foi criada pelo professor com o Bootstrap. O código HTML e CSS não tem muito segredo.
Nesse ponto criamos a função calcular() que recebe como parametros tipo e valor, onde tipo indica se é um operador(ação) ou um número(valor) e valor indica o valor da tecla.
Em seguida criamos os eventos onclick para cada botão que chama a função calcular() passando como parâmetro o tipo e o valor de cada botão.
Aula 197 - App Calculadora parte 2 - Implementando a lógica de cálculo
Para fazer a lógica da calculadora inicialmente criamos um seletor para verificar se o botão pressionado é um valor ou uma ação.
Em seguida fazemos a lógica do botão c. Nesse caso simplesmente passamos o value para ' '.
Os valores digitados são incluidos com concatenação no elemento do display.
O próximo passo é criar a ação para os operadores. Utilizamos para isso um seletor com operador lógico || que tem como resultado a concatenação do operador com os numeros digitados.
O resultado concatenado vira uma string com a operação matemática completa.
Para transformarmos essa string com a expressão matemática em uma expressão calculável pelo Javascript utilizamos o método eval() que faz exatamente essa conversão avaliando a expressão.
Por fim esse valor é atribuido ao value do input que demonstra o valor no display.
Aula 198 - Array básico - Introdução
Arrays são listas ordenadas. Basicamente são variáveis que nos permitem relacionar itens associados a índices(chaves).
Um array premite armazenar de forma relacionada diversos valores em uma única variável.
No Javascript precisamos declarar que os valores a serem inseridos na variável são do tipo array.
Aula 199 - Array básico - Prática
Para criar um array utilizamos a sintaxe:

var nome_variavel = Array()

ou

var nome_variavel = []

Criada a array podemos incluir os elementos atribuindo para eles um índice. O índice não precisa necessariamente ser numérico.
Podemos misturar elementos de diversos tipos em uma array (strings, numeros, boolean).
Quando criamos a array diretamente, sem especificar os índices o JS cria esses indices automaticamente iniciando do valor '0'.
Aula 200 - Extra - Diferença entre o atributo length de variáveis do tipo string e array
Em variáveis do tipo string o atributo length retorna o número de caracteres dentro da string. Já em objetos do tipo array o atributo retorna o número de elementos do array, porém este valor pode ser diferente do real. Isso porque isso depende de o índice estar sequencial, e iniciando em '0'.
Por exemplo quando criamos uma array como no exemplo:
var lista_frutas = [];
lista_frutas[1] = "Banana";
lista_frutas[2] = "Maçã";
lista_frutas[3] = "Morango";
lista_frutas[4] = "Uva";
o retorno do length do array é: '5'.
Isso porque ele considera o valor no índice 0 como empty. Se iniciarmos os índices em '5' teremos 5 elementos com valor empty
Aula 201 - Array multidimensional
Arrays multidimensionais ou bi-dimensionais são arrays de arrays, ou seja podemos através de uma variável e um índice acessar outro array.
Esse tipo de array é importante para criação de relatórios complexos com vários dados.
Note no exemplo que quando criamos o segundo array com índices 'a', 'b' e 'c' o length do array fica definido em '0'.
Aula 202 - Array - métodos de inclusão e exclusão de elementos
Maneiras programáticas de inclusão e exclusão de dados em arrays: push() : inclui objetos no final do array.
unshift() : inclui objetos no início do array rearranjando os índices.
pop() : exclui o elemento do final do array.
shift : exclui o elemento do início do array, rearranjando os índices.
Aula 203 - Array - métodos de pesquisa
Maneiras programáticas de pesquisa de dados em arrays: indexOf() : pesquisa o nome do elemento na array. Esse método é case sensitive.
Aula 204 - Array ordenação de elementos
Maneiras programáticas de ordenação de dados em arrays: sort() : faz a ordenação dos elementos em ordem alfabética / numérica. Considera o primeiro caracter para a ordenação, assim quando tentamos ordenar números temos divergencia na ordenação por valor absoluto. PAra resolvermos esse problema podemos criar uma função para fazer a ordenação matemática.

Array.sort(nomeDaFuncao);

function nomeDaFuncao(a, b) {
return a - b;
}
Essa função já é comum a propriedade sort() pois caso utilizemos ela com a chamada nomeDaFuncao() o próprio console dá o seguinte erro:

Uncaught TypeError: The comparison function must be either a function or undefined

Essa função também funciona caso os valores numéricos sejam passados como string pois o JS faz o casting dos valores ao se deparar com o operador '-' na função.
Aula 205 - Atividades para fixação do conteúdo
Criação de uma aplicação que adiciona e ordena elementos em um array.
Precisei fazer uma refatoração para criar uma variável para o document.getElementById('entrada').value que estava sendo repetida várias vezes.
Aula 206 - Estrutura de repetição parte 1 - Introdução
Estruturas de repetição, laços ou loops são estruturas que permitem que façamos a repetição de um comando ou bloco de códigos até que atinjamos um determinado ponto.
Aula 207 - Estrutura de repetição parte 2 - while
Loop while() sintaxe:

while(condição) {
// códigos a serem repetidos
}


Não podemos esquecer de criar uma interrupção para o loop, geralmente com o incremento da variável de controle.
Podemos também interromper a execução mediante alguma situação utilizando o comando break
Podemos ainda utilizar o comando continue, entretanto atenção pois dependendo da posição do incremento o continue pode gerar um loop infinito.
Aula 208 - Estrutura de repetição parte 3 - do while
Loop do while() sintaxe:

do {
// códigos a serem repetidos
while(condição)


Aqui também podedmos utilizar o break e o continue
Aula 209 - Estrutura de repetição parte 4 - For
Loop For() sintaxe:

for( variável de controle; condição; incremento) { // códigos a serem repetidos
}


Aqui também podedmos utilizar o break e o continue
Aula 210 - Praticando um pouco - Percorrendo e listando itens de arrays
Listando os itens de um array com o comando while.
Aula 211 - Praticando um pouco - Criando uma tabuada de 1 a 10
Criando a tabuada de 1 até 10 com laços for encadeados.
Atenção ao usar as variáves de contagem em laços encadeados para que não haja sobreposição de valores.
Aula 212 - Estrutura de repetição parte 5 - For in
Loop For / in sintaxe:

for( var x in nomeDoArray {
// código a ser executado utilizando o índice do Array
}


Note que o retorno do for/in armazena na variável x o valor do índice do Array, portanto x é o índice de cada elemento do Array, independente dos índices serem sequenciais ou serem do mesmo tipo.
Aula 213 - Estrutura de repetição parte 6 - Foreach
Em outras linguagens de programação o forEach é uma instrução de loop. Em JS o forEach funciona como uma função para Arrays. O funcionamento do forEach é semelhante ao do for /in.
Função forEach sintaxe:

nomeDoArray.forEach(function(valor, indice, array){}) {
// lógica ou código a ser executado selecionando o índice, ou o valor ou o array inteiro
}


Os parâmetros da função de callback podem ter qualquer nome.
O forEach encerra a busca no momento que ele encontar o último valor do array.
Um detalhe quando fazemos uma manipulação do array é que quando fazemos uma alteração em algum dos valores de um indice, no console se expandirmos o array veremos o valor atualizado (na apresentação do array aparece o valor antigo o valor atualizado essa inconsistencia ocorre apenas na expansão do array).
Podemos ocultar parâmetros na função de callback e passar apenas o valor que é o primeiro parâmetro na função.
Podemos também colocar a função em uma variável e passar essa variável para o forEach facilitando a leitura do código.
O forEach só funciona para índices numéricos e ordena de forma crescente. Os valores com índice diferentes de numeros inteiros são omitidos no forEach.
Aula 214 - Atividades para fixação do conteúdo
Resolução das práticas 210 e 211 com os laços alterados.
Aula 215 - Funções - Trabalhando com parâmetros variáveis
Em JS as funções tem uma instrução chamada arguments que retorna um tipo de array (não é um array pois não podemos utilizar métodos de array) com os parâmetros da função.
Quando passamos valores na chamada da função podemos acessar esses valores precorrendo o objeto arguments utilizando, por exemplo o for / in.
Com essa abordagem podemos, por exemplo realizar somas com valores de parâmetros sem termos passado esses parâmetros na construção da função. Para fazer isso podedmos utilizar a seguinte estrutura:

function soma(){
var r = 0;
for(var i in arguments) {
r += arguments[i]
}
return r;
}

soma(1, 2, 3, 4, 5, 6,)


Nesse caso, mesmo que não tenhamos declarado os parâmetros ou criado uma função para executar a soma temos a manipulação dos valores passados na função com o objeto arguments sendo percorrido como um array e executando a atribuição com soma na variável r
Essa técnica era muito utilizada na ECMAScript 2009 e já não é tão usual na ES6 (2015).
Aula 216 - Tratamento de erros com try, catch, throw e finally
Lógica para tratar erros que causam exceções na lógica do programa, evitando que os erros interrompam a aplicação. Permite ainda registrar esses erros. É um pilares do paradigma de programamção reativa.
Para o exemplo criamos um array bi-dimensional com um indice[1].
Vamos executar uma função que irá buscar um vídeo no indice[0] para forçar um erro. Essa chamada irá retornar undefined ou seja um valor inesperado. Nesse caso se tentarmos encontrar um valor do array bi-dimensional (no caso a propriedade) aí sim teremos um erro de execução. Nesse momento precisasmos de um tratamento de erro. Para as tentativas de executar uma ação quando utilizamos o try podemos 'pegar' o erro com o catch ou simplesmente finalizar a execução com o finally.
O finally pode ser executado diretamente após o try ou após capturarmos o erro com o catch. Em todos os casos vamos passar pelo finally.
Quando utilizamos o try / finally sem o catch não tratamos o erro portanto vamos ter um erro a menos que retornemos algo na função finally.
Já quando utilizamos o catch(erro) podemos tratar o erro e enviar uma mensagem desse erro para o backend através do parâmetro passado para o catch(). Esse tratamento pode ser feito através de uma função que recebe por parâmetro o erro.
O throw serve para lançar exceções. Podemos criar um objeto para lançar o erro e interromper a execução da aplicação. Preceba que o throw pode ser criado no início da aplicação de forma independente e uma vez iniciado para todo o resto da execução. O throw geralmente é utilizado junto com o catch. Ele sempre interrrompe a execução da aplicação.
Aula 217 - BOM - Introdução
BOM: Browser Object Model é uma forma de o JS se comunicar com recursos de browser. Diferente do DOM que manipula elementos HTML o BOM maipula elementos internos e externos do browser propriamente como a Janela, Tela, Posição.
Aula 218 - BOM parte 1 - Window
Enquanto no DOM acessamos os elementos através de document acessamos o BOM através do Window. Na verdade o document é um objeto do Window podendo ser referido como Window.document.
O método alert() é um exemplo de método do BOM.
Podemos abrir uma nova janela com o método window.open(). A sintaxe é:

window.open(URL, name, specs, replace)

Entre os parâmetros do método open temos o specs que entre outras coisas pemite definir o tamanho da janela a ser aberta.
Já para fechar uma janela aberta com o BOM podemos utilizar o método close(), entretanto para que ele opere na janela aberta devemos ter uma referência a essa janela através da atribuição do método de abertura a uma variável. Feito isso o método close() passa a ser um método do elemento cuja variável abriu a janela.
Caso tentemos utilizar o método close() no objeto window teremos a seguinte mensagem de erro no console:

Scripts may close only the windows that were opened by them.

Outro método que podemos utilizar é o window.print() que abre uma tela de impressão da página.
Para consultar outros métodos de manipulação do window consultar The Window Object
Aula 219 - BOM parte 2 - Screen
Screen fornece acesso a atributos relativos a tela do browser como largura e altura da parte interna do navegador. Podemos usar essas informações para melhorar a experiência do usuário avaliando o tamanho da tela por exemplo.
Para consultar os métodos do objeto screen podemos acessar The Screen Object
Entre os principais métodos temos availHeight / availWidth que mostra o tamanho da tela disponível excluindo as barras das janelas e o height / width que retorna o tamanho total da tela.
Esses métodos apresentam os valores máximos que o dispositivo pode alcançar e não o valor que a tela está no momento (para saber o tamanho da janela no momento devemos utilizar os métodos window.outerHeight / window.outerWidth e window.innerHeight / window.innerWidth).
Com esses métodos podemos fazer uma lógica para menu responsivo por exemplo.
Aula 220 - BOM parte 3 - Location
O location fornece acesso a atributos e métodos da URL atual. Podemos por exemplo forçar um redirecionamento afetendo a URL da aplicação ou atualizar a página atrvés do método reload. Quando clicamos em um link em uma página estamos atuando sobre o location.
Para consultar os métodos do objeto location podemos acessar The Location Object
Com o método window.location.href="URL_redirecionada" redirecionamos o site.
Outro método interessante é o window.location.reload() recarrega a página.
Aula 221 - BOM parte 4 - Timing
Métodos setTimeout / clearTimeout e setInterval / clearInterval permitem com base na definição de um intervalo de tempo executar uma ação de forma programática.
O setTimeout(ação, tempo_em_milissegundos) permite a execução de determinada ação uma vez após o tempo determinado.
O setInterval(ação, tempo_em_milissegundos) permite executar uma ação de forma contínua no intervalo de tempo informado. O setInterval executa de forma indefinida até ser interrompido.
Podemos com o método setInterval e o método window.location.reload() fazer uma ação para recarregar a página a cada n segundos.
Já com o método clearInterval() podemos parar a contagem do intervalo em determinada situação (se não setarmos o clearTimeout() o código continua rodando mesmo quando o valor ficar menor que 0).
Podemos fazer o mesmo com o clearTimeout() mas nesse caso seria utilizado para cancelar o setTimeout antes do término da função.
Aula 222 - App Game Mata Mosquito - Introdução
Desenvolver um jogo em JS para clicar na tela em mosquitos que surgem de forma aleatória e com velocidade selecionável.
Aula 223 - App Game Mata Mosquito - Iniciando o projeto
Criação da pasta do projeto e dowload das imagens.
Aula 224 - App Game Mata Mosquito - Definindo a dimensão do palco do jogo
Criação dos arquivos html e js do jogo.
A primeira coisa a se fazer é capturar as dimensões da tela com os métodos window.innerWidth e window.innerHeight.
Em seguida para que a atualização desses valores seja feita em tempo real criamos uma função para encapsular os métodos acima. As variáveis de altura e largura devem ser declaradas no escopo global da aplicação.
A função deve ser atribuida a tag <body> da página principal através do evento onresize para que monitore as alterações cada vez que o browser seja redimensionado.
Essas variáveis permitirão o redimensionamento da área de jogo de forma dinâmica.
Aula 225 - App Game Mata Mosquito - Criando posições randômicas
Criação do arquivo de estilo css, inclusão da imagem no html com a tag <img> e redimensionamento da imagem com uma classe no arquivo css.
Em seguida criamos a fórmula para as posições randomicas com a biblioteca Math.random() multiplicada pelos valores de altura e largura da tela. Utilizamos também o Math.floor() para arredondar os valores das posições pois as casas decimais são desnecessárias.
Para manipularmos a imagem de forma randomica na tela precisamos inclui-la através do JS. Para isso vamos criar uma variável que irá receber o método document.createElement('img') para criar uma tag <img> no HTML.
Feito isso, aplicamos esse elemento ao <body> como 'filho' com o método document.body.appendChild()
Outro detalhe é que nesse caso a referencia ao arquivo de script de ser colocada no final do <body> pois a referencia do document para realizar o appendChild é o body portanto ele precisa ser executado após a renderização da página. Podemos também manter o arquivo dentro do <head> e encapsular o código que cria o elemento <img> em uma função que será chamada no código html em uma nova tag de <script>.
Como criamos a <img> no JS, podemos excluir a tag do html principal.
Para posicionar o elemento de forma aleatória na tela utilizamos as propriedades de position no style do elemento.
Para isso setamos o elemento.style.left e elemento.style.top que receberá os valores das variáveis de posição randômica concatenada com a string 'px'. Devemos também setar o position como absolute elemento.style.position = 'absolute'.
Outro problema a ser resolvido é que o posicionamento não considera o tamanho da imagem. Desse modo temos que subtrair o valor dela do valor das variáveis position para evitar que a imagem saia da área da tela. Entretanto isso gera um problema para o caso de a posição ser 0. Nesse caso fazemos um operador ternário que irá garantir que se o valor randomico for igual a zero mesmo que ele fique negativo com a subtração seu valor seja no mínimo 0.
Aula 226 - App Game Mata Mosquito - Tamanhos randômicos
Para variarmos o tamanho da imagem utilizamos também a função Math.random() do JS, dessa vez multiplicando o valor por 3 (para termos 3 tamanhos diferentes) e arredondamos o valor para baixo com a função Math.floor(). Com isso temos a variação de valores entre 0 e 2.
Esse valor deve ser testado (com if / else ou com switch) e deve retornar o nome da classe que irá definir o tamanho da imagem do mosquito. Essa função será chamada pelo método elemento.className e assim atribuirá o valor retornado como classe da imagem.
Aula 227 - App Game Mata Mosquito - Lado A e lado B
Nessa parte vamos alterar a posição do mosquito (esquerda e direita).
Para isso criamos uma nova função com dois valores randômicos da mesma forma que os tamanhos randômicos.
Para fazer a mudança de lado da imagem utilizamos o atributo CSS transform: scaleX(1) e transform: scaleX(-1)(esse valor inverte a imagem no eixo X).
O retorno da função deve ser concatenado com o valor da classe que define o tamanho randômico.
Aula 228 - App Game Mata Mosquito - Criando e removendo mosquitos a cada ciclo de tempo
Para fazer com que os mosquitos apareçam a cada intervalo na tela utilizaremos o método setInterval().
Esse método executará uma função anonima que executará a função posicaoRndomica() a cada 1000ms. A sintaxe ficará assim:

setInterval(function(){
posicaoRandomica();
} ,1000)


Em seguida para fazer com que apareça um mosquito por vez na tela criamos um id para a imagem utilizando o atributo do elemento.
Esse id será manipulado com o document.getElementById().remove(), mas ele deve ser testado se existe antes, pois senão na primeira execução o código dará um erro pois o id do elemento vai retornar null.
Aula 229 - App Game Mata Mosquito - Criando o cenário
Criação dos estilos para o cenário. A imagem de fundo foi incluida como background-image do <body>.
Em seguida criamos as <div> para o painel que contará a vida e o tempo de jogo.
Feita a estilização desses componentes e criadas as tags <img> dos corações de vida ainda no html.
Aula 230 - App Game Mata Mosquito - Controlando os pontos de vida
Para fazer a lógica dos pontos de vida devemos entender o seguinte:
Quando clicamos no elemento ele deve ser removido da tela e nada deve acontecer (com os pontos de vida).
Se o elemento não for clicado antes da remoção automática então os pontos de vida devem ser afetados.
A primeira coisa a se fazer é tratar o clique no elemento. Para isso criamos no elemento o evento onclick. A esse evento vamos atribuir uma função que irá trata-lo.
Como a função está associada ao evento e consequentemente ao elemento podemos nos referir a esse objeto como this.
Assim para removermos o elemento caso clicado utilizamos a chamada this.remove() que é o mesmo que elemento.remove().
Para tratarmos o caso de não clique a tempo vamos voltar ao teste lógico if criado anteriormente que verifica se existe ou não o elemento na tela.
Para manipular os corações de vida vamos criar ids para cada ponto de vida. Com esses ids vamos alterar a imagem do coração de cheio para vazio. Essa mudança é feita utilizando o método getElementById(id).src='imagem'.
Para removermos os corações de vida substituimos as imagens de src coracao_cheio por coracao_vazio.
Por fim para o contador de vidas criamos uma variável que deve ser incrementada a cada vida perdida. Essa variável controlará as ids que irão manipular os corações e determinará o fim de jogo.
Aula 231 - App Game Mata Mosquito - Game Over
Para fazermos a apresentação da tele de fim de jogo (Game Over) vamos utilizar uma nova página através da manipulação do BOM com o método window.location.href
Dessa forma precisamos criar um a nova página html que será referenciada pelo location.
Essa página será estilizada com o Bootstrap.
Para isso incluimos a imagem de Game Over encapsulada nas classes do Bootstrap e com o flexbox centralizado utilizando as classes container, row, col e d-flex justify-content-center (ver utilização do Bootstrap).
Dentro desse container criaremos ainda um botão com as classes btn btn-dark btn-lg e com o evento onclick que irá chamar novamente o BOM dessa vez direcionando para a página inicial window.location.href = 'pagina_inicial'
Aula 232 - App Game Mata Mosquito - Adicionando o cronometro
Para fazermos o contador de tempo utilizaremos o método setInterval com uma variável que será decrementada a cada 1 segundo.
A função utilizada para o setInterval é apenas para fazer o decremento da variável tempo. Já para exibirmos o tempo do cronometro na tela criamos um <span> com um id e utilizamos o método document.getElementById('id').innerHTML = tempo.
O atributo innerHTML define o valor que será incluido entre as tags do elemento a que ele se refere.
Como o decremento do tempo ocorre antes de enviarmos ele para a tag <span> precisamos incluir o innerHTML com o valor da variável de tempo inicial no script inicial da página.
Em seguida precisamos criar uma lógica para parar o cronometro quando seu valor chegar a 0. Essa lógica com if detrminará a vitória caso o cronometro chegar a 0 e a vida ainda for maior que 0.
Feito isso precisamos parar a execução pois a função do setInterval continuará em execução. Para isso quando ocorrer a vitória devemos limpar a função com o clearInterval() recebendo como parametro a variável que inicia o setInterval (variável 'cronometro').
Mesmo assim ainda teremos a criação dos mosquitos pois a função que cria os mosquitos ainda estará em execução pois também utiliza uma função setInterval() (que está no <script> do documento html).
Precisamos portanto criar uma variável para armazenar a função setInterval que cria os mosquitos e também aplicar o clearInterval passando como parametro o nome dessa variável.
Para entender o memento de utilizar o clearInterval() precisamos limpar as funções que utilizam contadores de tempo no momento da vitória (momento que encerra o jogo, para de contar o tempo para perder vidas e para de gerar mosquitos).
Já quando o jogador perde a partida a aplicação chama uma nova página, portanto não precisa resetar os intervalos.
Aula 233 - App Game Mata Mosquito - Vitória
Em caso de vitória também vamos remeter o usuário para outra página.
Para isso criamos uma nova página copiada da página de vitória e apenas alterando a mensagem de game_over.png para vitoria.png.
Outra coisa que fiz foi ajustar no CSS o background-size para cover, pois a imagem de fundo está em 1280 x 1017 pixels. Para a maioria das telas está ok (acredito até que na resolução utilizada na aula), mas para a resolução do meu monitor estava ficando menor que o tamanho da tela e portanto os mosquitos estavam aparecendo fora da área de fundo quando ficava em tela cheia.
Aula 234 - App Game Mata Mosquito - Página inicial
Criar a página inicial para a seleção dos níveis de dificuldade e início do jogo.
A estrutura básica da página é a mesma das de vitoria e fim_de_jogo, utilizando o Bootstrap.
Inserimos um novo elemento com uma tag <select> e com as tags <option> que contém os diferentes níveis de dificuldade. Essa tag será encapsulada em uma <div> com a classe do Bootstrap mb-2 (define o margin bottom).
Em seguida criamos um evento onclick no botão que iniciará uma função iniciarJogo()
Essa função vai recuperar o valor da tag <option> selecionado através do comando document.getElementById('id_do_selection').value. O retorno desse valor deve ser testado para o caso de ser nulo (nesse caso retorna false) e caso positivo retorna o valor do atributo value do <option> selecionado.
Aula 235 - App Game Mata Mosquito - Aplicando o nível de dificuldade selecionado
Primeiramente precisamos alterar, quando selecionado algum nível válido, a página index.html (página inicial) para a página app.html (página do jogo).
Fazemos isso utilizando o windows.location.href
Para passarmos o valor das <option> passamos o parâmetro junto com o endereço html da página app.html utilizando o operador '?'.
Dessa forma utilizamos o endereço "app.html?" + nivel ou seja, concatenamos o valor de href com o valor recuperado na variável nivel.
Esse não é o modo convencional para tranferir o valor entre páginas.
Para tratarmos esse valor recebemos o endereço no arquivo app.js com o comando BOM window.location.href. Esse método encaminhará o valor completo enviado pela página. Para separarmos o valor de parâmetro utilizamos o método search da seguinte forma:

window.location.search

Esse método retorna apenas o parâmetro enviado com o '?'.
Para remover o '?' do valor recebido utilizamos o método replace para trocar o '?' por ''.
Uma vez que recebemos o valor como uma string sem caracteres especiais podemos fazer um teste lógico para cada string de dificuldade. Esse teste irá retornar um valor que será atribuido a uma variável que por sua vez será enviada para o setInterval da página app.html.
Aula 236 - App Game Mata Mosquito - Ajustes finais e considerações
Para finalizar o game precisamos redirecionar o retorno do botão 'Reiniciar' para a página inicial alterando as páginas do evento 'onclick'.
Por fim vamos alterar o cursor do mouse. Para isso acessamos no CSS indexador mais alto da página: o html.
No html aplicamos a propriedade cursor e definimos seu valor como cursor: url('imagem_do_cursor') 30 30, auto sendo que os valores são a posição para esquerda e para cima em relação a imagem.

Seção 9 - ECMAScript 2015 (ES6) e Orientação a Objetos

Aula 237 / 238 - O que é ECMAScript / Como utilizar o ECMAScript 2015 (ES6) em suas páginas?
Breve história da padronização ECMA.
Como utilizar a esspecificação ES6 em browsers sem suporte (considerando o curso em 2018). Utilizando o 'transpile' para converter códigos em ES6 para serem executados em ambientes ES5. Esse processo não deve ser mais necessário agora (em 2021) mas vamos fazer oss ajustess conforme necessário.
Aula 239 - Babel - Introdução e configuração.
O Babel é um transpiler que faz a conversão do ES6 para navegadores com padrão ES5. Na aula já há um aviso que ele não é mais necessário, portanto é util apenas para conhecimento.
Para incluir o Babel no projeto, utilizamos o método standalone recuperando o arquivo babel.min.js no site do Babel.
Para utilizar o Babel devemos incluir a indicação na tag dessa forma: <script type='text/babel'>. Isso é necessário para que o script entenda que deve ser intepretado pelo script do Babel incluido anteriormente.
Toda a codificação em ES6 deve ficar inserida dentro do <script> identificado como acima.
Outra inclusão necessária é uma <div id='output'>
Executando a página com o script Babel, quando inspecionamos os elementos podemos verificar que o código html possui dois <script>. Um com o código digitado e outro com a identificação type='text/javascript já convertido pelo Babel.
Aula 240 - Configurando highlight de sintaxe do ES6 no SublimeText
Configuração para o SublimeText.
Aula 241 - Operadores de declaração de variáveis Var e Let (com Babel) Aula 241 - Operadores de declaração de variáveis Var e Let (sem Babel)
O let é uma forma de declaração de variável implementada no ES6. A diferença para o var é que ele preserva o escopo onde a variável foi criada.
Lembrando, o JS tem três escopos: escopo global, escopo de função e escopo de bloco. O que 'identifica' um escopo diferente do escopo global é se a variável estiver dentro de um conjunto de { } que pode ser de uma função ou de um bloco de código.
Quando declaramos uma variável de escopo global com o operador var, podemos acessar essa variável de em qualquer parte do programa (em qualquer escopo) inclusive em window.nome_da_variável.
Quando criamos uma nova variável com o operador var, com o mesmo nome dentro do escopo de uma função, essa variável ficará acessível dentro da função e dentro dos blocos que estejam dentro dela, mas não fora do escopo da função. Assim a variável terá um valor dentro do escopo da função e seus blocos e outro valor no escopo global e seus blocos. As variáveis em escopo de função não sofrem o hoisting ou seja não 'sobem' de escopo (ficam restritas a função e seus blocos). Já uma variável criada em um bloco vai ter seu escopo elevado para escopo global caso esteja no escopo global ou para escopo de função caso esteja dentro de uma. Note que para a variável ser acessada no escopo da função a função deve ser chamada depois que a variável for criada. Portanto as variáveis criadas em escopo de blocos dentro do escopo global podem ser acessadas no escopo global, no escopo de função e no escopo de bloco, já uma variável criada dentro de um escopo de bloco que esteja dentro de uma função só poderá ser acessada dentro da função pois essa variável sobe apenas um nível.
Já quando utilizamos o operador let o escopo da variável é preservado. Note que o comportamento do let só faz diferença em escopos de bloco pois no escopo da função a variável não sofre 'hoisting' Portanto quando utilizamos o operador let para declarar uma variável em um bloco ela não ficará acessível fora do bloco retornando que a variável is not defined.
Com a criação do let e do const não se deve utilizar mais o var pois existe uma tendencia de ele ser removido em versões futuras do ECMA (não foi nessa mudança de versão do ES5 para o ES6 pois ele acabou de criar esse padrão).
A partir dessa aula não vou mais utilizar o Babel
Aula 242 - Análise de contexto 1 - Usando Var e Let
Aqui podemos ver como se comporta a variável criada com o operador var. Quando acessamos a variável criada dentro do bloco após sua criação seu valor passa a ser o valor atribuido dentro do bloco e não mais o valor atribuido no escopo global.
Aula 243 - Análise de contexto 2 - Usando Var e Let
Aqui podemos ver como se comporta a variável criada com o operador let. Quando acessamos a variável criada dentro do bloco após sua criação seu valor volta ao valor global, e só é alterada no contexto de bloco.
Se tentarmos alterar o operador da variável global que já foi declarada com o let e declarar no escopo de bloco com o operador var teremos um erro pois haverá um conflito de declaração de variável.
Aula 244 - Operador de declaração de variáveis Const
O const é outro operador de declaração de variáveis criado a partir do ES6 e tem o funcionamento parecido com o let. A diferença é que as variáveis criadas com o const não devem sofrer alteração durante a execução do código.
Uma boa prática para criarmos variáveis com const é utilizarmos o nome da variável em letras maiúsculas.
Uma característica das variáveis const é que não podemos deixar de atribuir valor quando a inicializamos, ou seja, ela exige uma atribuição, mesmo que seja undefined.
Não podemos também atribuir um novo valor para uma const.
Podemos entretanto criar uma nova const de mesmo nome dentro de uma função e com valor diferente.
Podemos utilizar a const para armazenar links para APIs, senhas de banco de dados e outros valores que serão utilizados pelo script e que não devem ser alterados.
Aula 245 - Template String
O template string é semelhante a concatenação de strings mas trabalha com uma interpolação de codificação JS com strings.
Para criarmos um template string utilizamos o símbolo ` ` (craze) para envolver o texto. Dentro deste sinal podemos escrever qualquer texto, sendo que os valores que serão resgatados de variáveis são declarados entre o sinal ${ }.
Podemos também incluir quebras de linha e o resultado será o que digitamos sem a correção pelo navegador ou pelo script.
Podemos também criar expressões ou executar funções dentro do template strings.
Aula 246 - Funções - Parâmetros default
Com os parâmetros default podemos atribuir valores para os parâmetros das funções em sua criação.
Esses parâmetros serão utilizados no caso em que a função seja invocada sem a atribuição dos valores.
Podemos passar apenas um parâmetro ou todos que serão substituidos conforme o caso.
Caso queiramos utilizar algum dos parâmetros default podemos definir na chamada da função esse parâmetro como undefined
Aula 247 - Funções - Arrow function
Arrow function é uma forma mais enxuta para criação de funções anonimas.
Para criarmos arrow functions utilizamos a tribuição a uma variável da mesma forma que com a função anonima, porém não precisamos utilizar a palavra function, apenas indicamos os parenteses com os parÂmetros necessários seguido de uma seta '=>' e as chaves que determinam o bloco de código que será executado. A sintaxe é a seguinte:

let variável = ( parâmetros ) => {
//código a ser executado
}


Quando temos apenas um parâmetro na função podemos omitir os parenteses, mas quando não recebemos nenhum parâmetro precisamos utiliza-lo.
Podemos também omitir as chaves e o return (return implícito) caso a função retorne apenas uma instrução simples (como no caso de uma operação matemática).
Um exemplo de utilização da Arrow function simplificada é quando temos uma função com um teste lógico do tipo if que podemos converter em operador ternário conforme exemplo abaixo:

Arrow function normal

let parOuImpar = (numero) => {
if (numero % 2 === 0) {
return "par";
} else {
return "impar";
}
};

Arrow function simplificada

let parOuImparSimplificado = (numero) => numero % 2 === 0 ? "par" : "impar";
Aula 248 - Introdução a Orientação a Objetos - Considerações preliminares
O paradigma de Orientação a Objetos no JS já está implementada desde 2009 com o ES5, entretanto a implementação era bastante limitada e possuia algumas limitações de contexto. Com as novas implementações no ES6 ficou mais simples de utilizar esse paradigma.
Paradigma é um padrão, uma forma de se executar algo.
O JS permite que no mesmo script desenvolvamos no mesmo bloco de código baseados no paradigma procedural e orientado a objetos.
Os princípios do paradigma procedural é o desenvolvimento de aplicaçãoes que seguem uma sequencia, que possuem estruturas de decisão (condicionais) e possuem também estruturas de repetição. A linguagem JS fornece suporte a funções que atendem esses requisitos.
Aula 249 - Introdução a Orientação a Objetos
Paradigma Procedural, exemplo:

let a = 10 let b = 7 let operador = 'mult' functrion calcular(a, b, operador) { if(operador === 'mult') { console.log(a * b) } } calcular(a, b, operador)
Aqui temos os pilares do paradigma procedural: a execução é sequencial, temos uma tomada de decisão com o operador if e não temos um laço de repetição por não haver necessidade.
Paradigma de Orientação a Objetos, exemplo:

class Calculadora { constructor() { this.a = 10 this.b = 7 this.operador = 'mult' } calcular(){ if(this.operador === 'mult') { console.log(this.a * this.b) } } } calculadora = new Calculadora() calculadora.calcular() Na orientação a objetos criamos uma classe que é uma abstração de alguma coisa, no caso, uma calculadora. No caso o ojeto é uma 'calculadora' pois o método que queremos executar é 'calcular'. Uma abstração é a forma como o programador enxerga as coisas.
As variáveis que declaramos em um objeto são seus atributos.
Para que uma aplicação seja escrita seguindo o paradigma de orientação a objetos ela deve seguir alguns pilares. São eles: abstração, encapsulamento, herança e polimorfismo.
Aula 250 - OO - Pilar da Abstração
A abstração é mais uma habilidade intuitiva e de conhecimento das coisas do que de programação. Para entender a abstração precisamos entender os quatro temas da abstração: Entidade, Identidade, Características e Ações.
Entidade é algo do mundo real que trazemos para dentro da aplicação.
Identidade é a representação única de cada objeto originados da entidade.
Características são os atributos do objeto.
Ações são os métodos do objeto.
Os atributos e métodos devem ser criados na medida que forem necessários para a aplicação, ou podemos declarar tantas características e tantas ações quanto forem necessárias para a regra de negócio de nossa aplicação.
Para criarmos a entidade ou objeto utilizamos a palavra chave class seguida do nome do objeto por padrão iniciando com letra maiúscula e em camel case.
Em seguida para a abstração vamos determinar as características necessárias para o objeto de acordo com a regra de negócio. Note que não devemos abstrair todas as características existentes no ojeto, mas apenas as necessárias. Por padrão os atributos são descritos em camel case com a primeira letra minúscula. Esses atributos são declarados dentro de um método constructor() que será responsável por 'construir' o objeto quando ele for instanciado. Dentro do construtor os atributos são definidos com o operador this. que conecta o atributo a classe que irá construir o objeto.
As ações de cada objeto são declaradas como funções e são os métodos do objeto. Elas fazem parte também da abstração e devem obedecer as necessidades do negócio. Os métodos assim como as funções podem receber parâmetros e executar instruções e operações e retornar valores.
Definidos atributos e métodos precisamos instanciar o objeto que será a criação da entidade e definição de sua identidade.
Para isso criamos uma variável e atribuimos a ela um new objeto. Aqui criamos efetivamente a entidade e sua identidade. A partir desse momento podemos acessar os métodos e atributos através do nome da variável (identidade do objeto) instanciada.
Uma vez que instanciamos vários objetos utilizando a mesma classe cada instancia do objeto manterá seus próprios valores, mesmo que alteremos o valor em um dos objetos.
Aula 251 - Reflexão - Da abstração a entidade
Na orientação a objetos a abstração é o pilar mais conceitual.
No paradigma procedural podemos criar o elemento através de variáveis que definem seus atributos e com isso gerar funções que executam seus métodos (ações). Entretanto quando temos diversos elementos que compartilham os mesmos atributos mas que tem valores diferentes no paradigma procedural devemos tratar esses valores em um array. Assim teremos que criar um array de cadeiras que em cada índice terá os atributos de cada cadeira. Para testarmos uma ação em determinada cadeira devemos chamar a ação na cadeira com o índice solicitado. Pelo exemplo podemos ver a complexidade de se executar esse processo no paradigma procedural.
No paradigma de OO criamos a classe com o método construtor. O construct() pode receber parâmetros que serão passados para os atributos no momento da construção do objeto. Podemos criar as variáveis, que no caso de objetos são os atributos com os mesmos valores que os parâmetros pois eles estão em escopos diferentes (o atributo está no escopo do objeto, o parâmetro está no escopo da função).
Aula 252 - OO - Pilar do Encapsulamento
Em OO o encapsulamento consiste em encapsular um objeto de modo a tornar o objeto seguro e reutilizável. O encapsulamento da visibilidade aos atributos e métodos conforme a necessidade ao defini-los como públicos ou privados. Um atributo ou método privado só pode ser acessado através do objeto criando uma camada de segurança.
A reutilização dos atributos e métodos encapsulados se dá através do terceiro princípio/pillar da OO que é a herança.
O encapsulamento não é suportado nativamente pelo JS, mesmo na versão ES6, portanto existe uma convenção que indica a intenção do programador que determinados atributos ou métodos sejam public, private ou protected.
Quando criamos um classe de objeto e construimos seus atributos, para indicar que aquele atributo deveria ser privado iniciamos o nome do atributo com '_'. Isso não impede que esse atributo seja acessado diretamente no programa, mas indica ao desenvolvedor que esse atributo 'não deve' ser acessado diretamente mas sim através de uma função como deveria ser se esse atributo fosse private.
Para acessarmos esses atributos devemos criar os métodos get e set que retornam o valor do atributo propriamente. Assim para um atributo
this._atributoPrivate
criamos um método
get atributoPrivate() {
return this._atributoPrivate
}

Essa solução é necessária nas linguagens em que a OO é nativa, mas deve ser utilizada no JS mesmo que ele possa acessar os atributos diretamente por uma questão de padrão. Nesse caso o acesso ao atributo se dá através de uma pseudo-variável que na verdade é a 'função' criada pelo get. Quando invocamos essa função não precisamos utilizar o () pois o JS entende, quando utilizamos o get que aquela pseudo-variável se refere aquela função
O mesmo fazemos com o set porém como ele altera o valor dos atributos criamos uma lógica que irá proteger o atributo de ser acessado diretamente. Podemos, como no exemplo, verificar se o valor atribuido consta no array de valores definidos no construtor e impedir que se atribua valores inválidos.
Aula 253 - OO - Pilar da Herança
O pilar da herança em OO garante duas vantagens na programação. O código se torna reutilizável e de fácil manutenção.
Quando analisamos os objetos em uma aplicação devemos abstrair esses objetos e em certas ocasiões reagrupar atributos que pode ser comuns a mais de um objeto em outro objeto pai. Criamos com isso super-classes e sub-classes. As sub-classes podem ser chamadas de classes especializadas. As classes filhas herdam ou extendem os atributos e métodos da classe pai.
Para que as classes filhas contenham os atributos da classe pai devemos extender a super-classe nas sub-classes com a palavra extends. Além disso no método construtor, antes de declarar os atributos específicos devemos chamar o operador super().
Uma classe filha herda os atributos da classe pai e todas as heranças recebidas por ela.
Do ponto de vista da manutenção, caso em determinado momento precisemos adicionar novos atributos para nossos objetos, caso seja um atributo comum a todos basta cria-lo na classe pai, que automaticamente todos os filhos e netos herdarão esse atributo.
Aula 254 - Operador Super
O operador super() é quem concede acesso ao método construtor da' classe pai, ou seja deve sempre ser incluido dentro do construtor das classes filhas.
Podemos passar parâmetros diretamente para o construtor e podemos passar parâmetros para as classes pai através do operador super(). Desse modo quando instaciamos o objeto podemos definir cada atributo dele em parâmetros na instancia e passar para cada construtor específico definindo seus parâmetros no constructor() e enviando pelo super().
Aula 255 - OO - Pilar do Polimorfismo
O pilar do polimorfismo fundamentalmente trata da reutilização e sobrescrita de métodos, ou seja, quando temos a herança de métodos o objeto filho não precisa necessariamente se comportar como o objeto pai. Assim podemos recriar métodos ou atributos que são herdados de uma classe pai para se adaptar a determinada classe filha. Com isso não precisamos remover determinado atributo ou método de uma super-classe porque ela não atende apenas uma das sub-classes, precisamos apenas redefini-la na classe filha específica.
Aula 256 - Objetos literais / estáticos
Objeto literal já existe no JS anteriormente ao ES6. Como já estudamos podemos criar objetos através de classes que contém atributos e métodos e são construidos quando os instanciamos através do operador new.
Os objetos literais são pares de nomes(atributos / chaves) e valores atribuidos a uma variável. Os nomes e valores são incluidos em '{ }' separados entre si por ':'. Cada conjunto de nome: valor são separados por ','.
Podemos declarar funções como valores.
Assim como no objeto construído através de OO, o objeto literal também pode ser referenciado com o this desde que a função esteja dentro do escopo do objeto literal.
O objeto literal não precisa ser instanciado como nas classes e podem ser acessados diretamente pelo nome da variável seguido do operador '.' e o nome do método ou atributo que se deseja acessar.
Utilizamos objetos literais quando não é necessário criar uma coleção de dados, mas sim utilizar os dados apenas uma vez, por exemplo quando temos um formulário. Nesse caso os dados são montados em um objeto literal, convertidos para JSON e armazenados no servidor.
Aula 257 - Objetos literais - Melhorias de notação
Quando atribuimos valores a variáveis e criamos objetos literais utilizando esses dados os valores definidos como chaves e os valores definidos como valores das chaves podem ser os mesmos pois o JS identifica quando é um e quando é outro.
Com a nova versão do ECMA quando temos os nomes das variáveis como nome das chaves não precisamos mais definir a notação chave: valor, bastando utilizar o nome da variável.
O mesmo ocorre com as funções. Não é mais necessário declarar a chave como nome da função e depois dos ':' declarar a função com a palavra function. Basta agora declarar o nome da chave seguida de ( ) e descrever o código da função.
De qualquer modo podemos definir o nome da chave diferente do nome da variável discriminando os dois do modo antigo.
Aula 258 - Objetos literais - Modificando valores
Podemos alterar os valores de um objeto literal simplesmente chamando o nome do objeto seguido de '.' e o nome do atributo a ser modificado da seguinte forma:
nome_do_objeto.chave = novo_valor
Aula 259 - Objetos literais - Criação dinâmica de pares nome/valor
É possível também criarmos novos grupos de chave/valor apenas referenciando o nome do objeto literal com o operador '.' e o novo nome/chave seguido de sinal de atribuição '=' e o valor da chave.
Do mesmo modo podemos definir funções como valor utilizando por exemplo arrow functions conforme o exemplo:
nome_do_objeto.nome_da_função = () => {código_da_função}
Aula 260 - Objetos literais - Objetos únicos
Mesmo quando um objeto literal é atribuido a uma nova variável ele não é copiado ou recriado. Apenas é feita uma referência ao objeto principal.
Aula 261 - Funções construtoras - Criando objetos
Até aqui criamos objetos através de classes e do método constructor() (disponível na versão ES6), e através de objetos literais(disponível na versão ES5 com melhorias na versão ES6). Em seguida vamos estudar como criar objetos através de funções construtoras(disponível na versão ES5 e mantido na versão ES6). Esse método é menos moderno que os demais mas ainda é importante pois faz parte da essência do JS.
Quando criamos objetos com funções construtoras devemos criar os atributos com o operador this mas sem o método constructor() pois não é uma notação baseada em classes mas sim uma função que será construida com o operador new.
Da mesma forma os métodos do objeto são criados com o operador this. Esses métodos receberão como parâmetro uma função, ou seja, serão também atributos do objeto.
Para fazermos o encapsulamento dos métodos, devemos criar os atributos que farão o papel de getter e setter. Desse modo mantemos os pilares da OO, mesmo que possamos executar a função diretamente no atributo.
Criada a função construtora devemos utilizar o operador new para criar o objeto, do mesmo modo que na criação por classes. Feito isso podemos utilizar os métodos criados da mesma forma que no modelo de classes.
Apesar de as sintaxes de constução por classes ou funções serem parecidas, mas com alguns comportamentos de contexto diferentes. Essas diferenças permitem que nas funções construtoras tenhamos encapsulamentos dos atributos para torna-los públicos ou privados.
Aula 262 - Funções construtoras - Encapsulando atributos e métodos
A ideia do encapsulamento é que atributos e métodos sejam protected, public ou private, ou seja são operadores que permitem definir niveis de visibilidade aos atributos e métodos. Esse princípio é um pouco limitado no JS pois não podemos definir a visibilidade em atributos e métodos nas classes. Apenas fazemos isso por convenção. Portanto nos modelos baseados em classes todos os atributos e métodos são públicos.
Já quando criamos objetos através de funções construtoras, podemos definir atributos privados quando os criamos não com o operador this mas sim como variáveis dentro do escopo da função. Essas variáveis, por terem escopo local se comportam como se fossem atributos privados que só são acessados dentro da função e não são visíveis fora dela.
No exemplo de aceleração da aula anterior temos um valor de velocidade máxima que não está encapsulado e pode ser acessado fora do objeto. Entretanto é um atributo que deveria estar protegido.
Nesse caso ao declararmos esse atributo como uma variável de escopo local ela não poderá ser alterada fora do escopo da função. Mesmo que tentemos alterar seu valor ele nao será acessado nos métodos do construtor.
Podemos também crair métodos privados com funções atribuidas a variáveis do escopo local. Essas funções também só serão acessíveis dentro do escopo da função, portanto esses métodos serão privados.
Aula 263 - Funções factory
Funções Factory(design pattern factory) não é uma implementação mas sim um conceito de programação que pode ser aplicado nos códigos. Elas combinam as chamadas de função com o retorno de objetos literais que podem ser criados por parâmetros.
Quando criamos uma função do tipo Factory declaramos os atributos e nos campos de valores indicamos parâmetros que serão passados pela função. Dessa forma quando criamos uma variável e lhe atribuimos como valor a função factory criada, em seus parâmetros passamos os valores para a criação de um objeto literal.
Podemos ainda remover os nomes das chaves caso o nome das variáveis de parâmetro sejam as mesmas das chaves como vimos na aula sobre melhorias dos objetos literais.
Entre as vantagens das funções do tipo factory a principal é o dinamismo na criação de objetos literais principalmente quando vamos receber dados através de uma lógica passada, por exemplo, por uma lógica que trata dados através de requisições http. Texto sobre Factory
Aula 264 - Prototype - Introdução
Em JS todos os objetos descendem de Object. Por traz disso exite um conceito chamado prototype. Quando criamos classes e instanciamos objetos estamos utilizando uma sintax sugar pois o JS lida com os objetos de forma diferente de outras linguagens.
Prototype é um modelo(protótipo) de alguma coisa. Quando criamos um objeto no JS ele é um descendente de Object.
Quando criamos obejtos através de métodos diferentes como no exemplo da aula (objeto literal, função construtora e classe) ao analisarmos o retorno desses objetos no console vemos que todos possuem um atributo chamado __proto__: Object. Ou seja como visto acima todos os objetos, independente de como sejam criados descendem de Object e Object não é um objeto e sim uma função.
Aula 265 - Prototype - Herança
Como visto qualquer objeto criado em JS é filho de Object. Aqui vamos entender as cadeias de protótipos para poder compreender as heranças entre objetos.
Quando criamos objetos, muito embora todos sejam filhos de Object eles não são referenciados entre eles portanto seus atributos não são herdados.
Para extender os atributos de um objeto para outro podemos utilizar o atributo __proto__ comum de Objetct passado como parametro no objeto herdeiro tendo como valor o nome do objeto que vai tranmitir o atributo a ser herdado.
Neste caso se atribuirmos um valor para um atributo que seja herdado o JS vai sobrepor esse valor pelo de menor escopo, ou seja, o valor mais próximo do objeto que se está referenciando.
Uma observação é que o Object.prototype pode armazenar atributos que se aplicarão a todos os objetos que forem criados, pois como foi visto ele é pai de todos os objetos. Assim se definirmos um atributo em Object.prototype ele ficará automaticamente acessível em qualquer objeto criado no código. Essa propriedade deve ser utilizada com cuidado pois uma vez atribuido o atributo diretamente em Object ele ficará disponível globalmente.
Aula 266 - Operador Rest/Spread parte 1
Os operadores rest/spread tem a função de juntar(rest) ou espalhar(spread) estruturas de dados.
O operador para rest/spread é representado por .... Na função de espalhamento podemos por exemplo espalhar uma string, ou seja separar cada caractere da string como um elemento separado. Podemos por exemplo agrupa-los em um array que terá cada caractere como um elemento.
Outra possibilidade é utilizar o spread para separar os elementos de um array e inclui-los em outro array indexado no array resultante.
Podemos também espalhar atributos de um objeto em outro objeto criando novos atributos para o objeto resultante.
Aula 267 - Operador Rest/Spread parte 2
A função spread/rest no modo de junção é muito utilizado em funções.
Quando precisamos passar uma quantidade indefinida de parametros para uma função podemos utilizar o rest seguido do nome do parametro da função para que os dados passados na chamada da função sejam enviados em formato de array. Tendo esse array montado podemos percorrer seus valores de modo a poder trabalar com esses dados na função.
Podemos ainda passar um parametro fixo e passar outro parametro com a função rest.
Aula 268 - Destructuring Assignment parte 1
O destructuring é um operador de desetruturação. Ele tira valores de dentro de uma estrutura que pode ser um array ou um objeto.
Quando precisamos acessar diversos elementos de um array podemos atribuir cada um a uma variável tendo como seletor o índice do array. Entretanto quando temos muitos valores essa prática é inviável.
O operador destructuring é representado pelo token (caracteres) [ ] colocados à esquerda da atribuição podendo ser iniciado com let ou const.
Dentro do token [ ] do destructuring colocamos os nomes das variáveis que serão atribuidas a cada indice do array. Caso queiramos pular algum dos valores do array podemos deixar o espaço em branco apenas separando por ','.
Podemos criar nomes de variáveis além dos valores contidos no array. Neste caso teremos um retorno undefined. Nesse caso podemos atribuir valores default para as variáveis que serão retornados caso o valor recuperado seja undefined.
Podemos utilizazr o destructuring também em arrays multidimensionais. Para isso devemos inserir dentro do operador '[ ]' novamente '[ ]' para cada matriz do array multidimensional.
Aula 269 - Destructuring Assignment parte 2
Vamos ver a utilização de destructuring em objetos.
Antes porém vamos entender a composição em objetos
A composição nada mais é que a criação de objetos dentro de objetos. Quando o objeto, classe ou função construtora tem apenas um conjunto de atributos e métodos dizemos que seu tipo de composição é é um. Já quando temos um objeto como valor de um atributo de outro objeto temos a composição tem um.
Para fazer o destructuring em objetos utilizamos o token de objeto { }. Os nomes das variáveis para fazer o destructuring de objetos são os nomes dos atributos do objeto. Podemos alterar esse nome outros nomes atribuindo o valor para essas variáveis da seguinte forma: nome_do_atributo: nome_da_variável.
Também podemos passar valores default para atributos inexistentes nos objetos da mesma forma que nos arrays.
Do mesmo modo que nos arrays multimensionais, podemos também acessar objetos dentro de objetos. Para isso a sintaxe é:
let { nome_do_atributo: { atributo_do_objeto_interno1, atributo_do_objeto_interno2} }
Aula 270 - Destructuring Assignment parte 3
Quando trabalhamos com arrays podemos passar seus valores para funções selecionando seus índices.
Podemos também passar na chamada da função o array completo e selecionar os itens necessários utilizando a notação de destructuring como parametro na função. Neste caso aplicam-se todas as propriedades estudadas anteriormente.
O mesmo ocorre com os objetos, lembrando que nesse caso utilizamos o token '{ }' e chamamos os atributos pelo seu nome no objeto.
Aula 271 - Destructuring Assignment parte 4
Utilizando o destructuring com o rest.
Podemos separar os valores de arrays combinando os operadores destructuring e spread/rest.
Aula 272 - App Orçamento Pessoal - Introdução
Nesta aplicação vamos fazer um pequeno sistema de orçamento utilizando a função Storage que existe nos navegadores modernos. Esse recurso pode ser substituido por um banco de dados no back-end.
Aula 273 - App Orçamento Pessoal - Iniciando o projeto
Para iniciar o projeto vamos incluir o Bootstrap v 4.0.0 com as dependencias do JS com os seguintes scripts:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />

<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous" ></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous" ></script>

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous" ></script>


Em seguida o arquivo do font Awesome. Para inserir o link do Font Awesome entrar com a conta e selecionar a opção Font Awesome CDN para copiar o link das fontes.
O script será o seguinte:

<script defer src="https://use.fontawesome.com/releases/v5.0.8/js/all.js" integrity="sha384-SlE991lGASHoBfWbelyBPLsUlwY1GwNDJo3jSJO04KZ33K2bwfV9YBauFfnzvynJ" crossorigin="anonymous" ></script>

Copiei o projeto da aula que foi desenvolvido em Bootstrap, sem grandes diferenças (dá para entender o código mas evidentemente preciso me aprofundar no desenvolvimento).
Nesse momento a apresentação do App já está visível, mas sem nenhuma funcionalidade.
Aula 274 - App Orçamento Pessoal - Criando, incluindo e testando o arquivo app.js
Criar e incluir o arquivo app.js na aplicação. O arquivo foi incluido no <head> das páginas e foi apenas incluido um alert para verificar se está acessível.
Aula 275 - App Orçamento Pessoal - Cadastro de despesa parte 1
Vamos começar a criação da lógica da aplicação com o Cadastro de Despesas. Para isso vamos monitorar o evento onclick do <button> da página index.html para executar a função cadastrarDespesa().
Note que no html os campos que serão manipulados já possuem ids para que possamos manipula-los no JS.
Aqui iniciamos a implementação.
Primeiramente criamos o evento onclick no <button> responsável pela inclusão de eventos. Esse evento irá invocar a function cadastrarDespesa().
Essa função irá acessar os dados através do método document.getElementById para a id de cada um dos itens que iremos armazenar.
Cada um dos valores será armazenado em variáveis próprias. Para recuperarmos os valores temos duas opções:
A primeira é recuperar o value diretamente na atribuição da variável da seguinte forma:
let variavel = document.getElementById('nome_da_id').value

A segunda é recuperar o value diretamente quando chamamos a variável:
variavel.value

A melhor forma de recuperar os valores é a segunda pois não vinculamos a variável ao value mas ao elemento.
Não esqueça do escopo das variáveis.
Aula 276 - App Orçamento Pessoal - Criando a classe Despesa
Aqui iremos criar uma classe para o objeto despesa.
Primeiro criamos uma classe para as despesas e com o método constructor incluimos todos os atributos necessários.
Em seguida, dentro da função de cadastro, vamos instanciar o objeto Despesas() que receberá como parâmetros os valores recebidos por getElementById.
Devo me atentar para as sintaxes de construção de objetos e classes
Esses parametros devem ser incluidos no método construtor e seus valores atribuidos as variáveis da classe.
No exercício foi incluido na tag <option> o value=" " pois como não havia valor padrão, caso o campo ficasse em branco o objeto recuperava o valor do campo (no caso 'Tipo').
Aula 277 - Extra - Web Storage
Existem vários recursos de armazenamento de dados. O mais comum antes do HTML 5 são os cookies. Os cookies são dados armazenados no client-side. Sempre que há uma requisição http os cookies são anexados a essa requisição de modo que o servidor possa extrair, analisar e processar seus dados com base nas informações cadastradas. Esse recurso é importante pois identifica o usuário no client-side. Se esses dados estivessem no server-side seria necessário fazer uma identificação do usuário para então processar os dados consultados.
Atualmente temos as opções de Local Storage e Session Storage que trabalham de modo semelhante aos cookies, entretanto os dados não são anexados às requisições http, ou seja ficam armazenados no navegador como em um banco de dados. A diferença de Session Storage e Local Storage é que o session só mantém os dados enquanto a seção do browser está aberta. Já o local storage persiste os dados mesmo que o navegador seja encerrado, ou seja, mantém os dados até que eles sejam intencionalmente removidos.
Além dos métodos já citados temos também o IndexedDB e Web SQL que são formas de armazenamento com recursos mais avançados.
Importante estudar esses métodos.
Aula 278 - App Orçamento Pessoal - Cadastro de despesa parte 2
Para incluir os dados recebidos pelo objeto despesa utilizamos uma função que irá executar o método localStorage.
Com o método localStorage podemos utilizar a propriedade setItem que irá receber dois parâmetros: a identificação do objeto que vamos armazenar e o dado que vamos armazenar, que deve ser encaminhado como um objeto JSON.
Devemos portanto converter os dados recebidos do objeto para esse formato. Para fazermos isso utilizamos um método do JS chamado stringify. A função completa para a criação desta rotina fica assim:
nome_da_funcao(dados_a_serem_enviados)

function nome_da_funcao(parametro) {
localStorage.setItem('identificacao_do_objeto', JSON.stringify(parametro))
}
Com essa função inserimos os dados no Local Storage, entretanto os dados são armazenados em uma chave fixa. Assim a cada nova inserção de dados os dados anteriores são sobreescritos.
Aula 279 - Extra - Objetos literais vs Notação JSON
Os objetos literais são bastante semelhantes a notação JSON e em muitos casos confundem o programador.
Quando criamos um objeto literal utilizamos a notação:
{atributo: 'valor_em_string', atributo: valor_numérico}
Já no JSON temos todos os dados como uma string única da seguinte forma:
'{"atributo": "valor_em_string", "atributo": valor_numérico}'
Note que no JSON temos a utilização de ' ' para criar o JSON e " " para identificar os itens em seu conteúdo. Esses sinais podem ser invertidos como em qualquer string.
O importante na diferença de objetos literais e de elementos JSON é que os objetos literais só existem dentro da aplicação, ou seja não podem ser acessados como objetos fora do contexto em que foi criado. Para que haja a comunicação dos objetos com outras camadas de aplicação precisamos encaminhá-los em um formato que seja compreendido de modo genérico, no caso, em um formato de texto. O JSON não é o único método de transferência de dados entre aplicações, mas é um dos mais utilizados pois pode ser interpretado por qualquer linguagem de programação.
O JS nativamente tem dois métodos para a manipulação de dados JSON: o método JSON.stringify() converte um objeto em JSON e o método JSON.parse() que faz o inverso.
Aula 280 - App Orçamento Pessoal - Criando a classe BD e índices dinâmicos
Para que possamos manter vários dados no Local Storage vamos criar uma classe para um objeto Bd e um índice dinâmico para que os valores não se sobreponham.
A classe criada será responsável pelo método gravar(), ou seja, gravar deixará de ser uma função para ser um método da classe Bd. Consequentemente não será mais chamado com função mas como método da instancia de Bd.
Na classe Bd faremos a lógica para implemantação das chaves de índice. Para isso utilizaremos o método localStorage.getItem(). Da mesma forma que o setItem insere dados em localStorage, o getItem vai recuperar o último valor de chave inserido.
Como não temos nenhum id em nosso Local Storage, teremos um retorno null. Para verificarmos se temos algum valor de id fazemos um teste lógico com if. Para tanto criamos uma variável id e caso seu valor seja null atribuimos a ela o valor '0'.
Em seguida criamos a lógica para implementar o id dinâmico a cada execução do método gravar()
A classe Bd será criada portanto da seguinte forma:
Primeiro criamos um método constructor() que terá a variável id que será recuperada com o método localStorage.getItem(). Esse valor será testado e se for null será atribuido valor '0'.
Em seguida executamos o método gravar(). Esse método irá executar o método getProximoId() que vai recuperar o valor do id com o método getItem e irá retornar o valor recuperado acrescido de '1'.
Feito isso o método gravar irá executar o método setItem() com o valor do id e o valor recuperado do JSON.stringify() com os dados inseridos na página. Por fim o método gravar() irá atribuir, também com o método setItem o valor de 'id' para a chave 'id'.
Aula 281 - App Orçamento Pessoal - Validando dados antes do registro parte 1
Implementação de validação dos dados antes do registro que ou aramazena as informações ou exibe uma mensagem para o usuário que os dados estão incorretos.
Para validar esses dados vamos manipular a classe Despesa para verificar os valores dos atributos do objeto criado. Fazemos isso criando um método na classe Despesa chamado validarDados(). Esse método fará parte de um teste lógico if que verificará se o retorno é vardadeiro. Caso seja true ele executa o método bd.gravar() caso contrário ele envia uma maensagem de erro.
Para verificar os valores em cada atributo vamos utilizar o comando for in que será executado no método validarDados(). Esse comando vai percorrer todos os atributos do elemento. A sintaxe para essa vaerificação é:

for(let i in this){
console.log(i, this[i])
}


Entendendo fazemos um for onde para todos os atributos ('i in') no objeto da classe ('this') vamos ter como retorno o 'i' (atributo) e o 'this[i]' (valor que foi atribuido).
Devo relembrar o for in pois foi uma operação que eu não estudei muito
Dentro do laço for in faremos um teste lógico if para verificar se qualquer dos valores dos atributos é undefined ou ' ' (vazio) ou null. Caso algum desses testes for verdadeiro retornaremos false para o teste lógico que valida os dados. Note que DEVEMOS retornar true caso o teste lógico atenda a todas as situações, caso contrário não teremos o retorno esperado.
Aula 282 - App Orçamento Pessoal - Validando dados antes do registro parte 2
Para mostrar as mensagens ao usuário em caso de gravação dos dados e no caso de dados inconsistentes vamos utilizar o recurso Modal do Bootstrap. Após inserir o código do modal fizemos alguns ajustes no conteúdo dos textos a serem exibidos e alguns ajustes nos botões a serem utilizados.
Para executar o modal o Bootstrap utiliza um botão que executa um código JQuery para alterar o display do modal de none para block (podemos ver isso inspecionando a janela aberta pelo modal e analisando a <div> que encapsula o modal).
O código JQuery que fará a maipulação do modal será inserido na lógica de validarDados() do nosso app com o seguinte comando:

$('#erroGravacao').modal('show')

Nesse comando o #erroGravacao é o id da <div> que encapsula o modal.
No exemplo quando removemos um botão removemos o botão close padrão do Bootstrap. Esse botão tem uma propriedade que não tem no botão que deixamos assim precisamos inserir a propriedade data-dismiss="modal" no botão que fecha nosso modal.
Para o modal de sucesso apenas copiamos o modal de erro e ajustamos os valores, alterando os textos exibidos, o texto do <button>, as cores dos elementos e a id do modal que controla sua exibição.
No código JS apenas incluimos o código JQuerry com a id correta na lógica de sucesso.
Aula 283 - App Orçamento Pessoal - Desafio
O desafio foi criar de modo programático as alterações nos campos dos modais de modo que fosse necessário apenas um modal no código html que fosse alterado pelo JS em cada ocorrência (sucesso ou erro).
Para isso utilizamos as ferramentas de manipulação do DOM document.getElementById.innerHTML e document.getElementById.className para manipular os conteúdos das tags e as classes do Bootstrap. Na minha resolução criei variáveis para cada elemento.
Aula 284 - App Orçamento Pessoal - Listando despesas parte 1
A partir de agora vamos iniciar a lógica para consulta dos dados inseridos no Storage. Para isso vamos criar a função carregaListaDespesas() e o método recuperarTodosRegistros().
A função carregaListaDespesas() vai ser chamada no evento onload() na tag <body> da página consulta, pois uma vez que chamamos esta página queremos que seja apresentados os itens armazenados. Já o método recuperarTodosRegistros() será criado na casse Bd.
Para recuperar os itens utilizaremos o método localStorage.getItem() com uma lógica para percorrer os itens de acordo com o número de ids registradas. Para recuperar o valor de quantodades de ids vamos utilizar o valor armazenado na chave id que contém o último valor e serve de base para as próximas chaves.
Com esse valor podemos fazer um loop for para percorrer todos os ids e recuperar em uma variável a descrição da despesa. Esses dados serão retornados em JSON e deve ser convertido com o método JSON.parse(). Com isso vammos gerar objetos literais que podem ser manipulados pelo app.
Com os dados em formato de objetos literais precisamos criar arrays de dados. Para isso vamos utilizar o push() dos objetos literais convertidos em despesa para o array despesas.
Nesse momento temos mais uma situação para resolver. Caso tenhamos excluido algum valor do Local Storage o índice desse valor ficará vazio e retornará null no array de despesas. Para resolver isso temos duas opções: podemos remover a entrada null na lógica que controla a view ou filtrar na lógica que recupera os dados para que o push não recupere dados nulos ao criar o array. Fazemos isso através de um teste lógico if que verifica se despesas é '===' null. Se sim retornamos continue que prossegue com o loop pulando essa iteração (no meu caso utilizei a lógica inversa !== ).
Em seguida vamos transferir esses dados para a função que o chamou e atribuir a uma variável do tipo array.
Note que no método que recupera os dados recuperarTodosRegistros() criamos uma variável despesas para armazenar o array de dados recuperados. Na função carregaListaDespesas() criamos uma variável despesas para armazenar o array gerado no método bd.recuperarTodosRegistros(). Essas duas variáveis despesas embora tenham o mesmo nome e o mesmo conteúdo são diferentes pois pertencem a escopos diferentes.
Aula 285 - App Orçamento Pessoal - Listando despesas parte 2
Aqui vamos transferir os valores armazenados no array criado anteriormente para uma tabela para apresentar esses valorres na tela de consulta.
Precisamos criar os nós para os itens $lttd> e <tr> com os dados formatados para a tabela conforme o array recuperado.
O primeiro a se fazer é criar uma id no <tbody> que irá receber os dados para podermos acessa-lo com o getElementById. Criada a variável que representará o <tbody> vamos percorrer os elementos do array despesas para separar os itens com o comando forEach(). Esse forEach separa cada uma das linhas de despesas em objetos individuais. Com esses objetos separados vamos inclui-los no html através da tabela.
Para inserir as linhas na tabela utilizaremos o método insertRow() (esse método não aperece nas opções do VSCode). Aplicado esse método a listaDespesas() serão criadas automaticamente tantas linhas (<tr>) quanto o número de itens do array despesas. Essas linhas devem ser aramzenadas em uma variável que por sua vez vai acessas os itens individualmente e encapsula-los em <td>.
Para inserir dados em <td> utilizaremos o método insertCell (através da variável que referencia as <tr>). Esse método deve receber como parâmetro o número da célula da tabela (iniciando em 0). Portanto devemos criar uma para cada coluna da tabela.
Para cada célula criada vamos agora inserir com o método innerHTML os valores recebidos no parâmetro da função do método forEach().
No caso do Tipo os valores recebidos são em números(string de numeros) mas a descrição é em texto. Para fazer o ajuste da apresentação utilizamos um switch/case com as opções a serem representadas de acordo com o número recebido do array.
Aula 286 - App Orçamento Pessoal - Desafio 2
O desafio é limpar os dados dos campos quando um registro for gravado. Executei isso com uma função que passa o value = ' ' para todos os campos. Na versão do professor ele inseriu os valores ' ' na própria lógica do cadastro em vez de criar uma função. Desse modo ele pode chamar os campos pelos nomes das variáveis do escopo local. Como eu criei uma função fiz as chamadas utilizando o document.getElementById de cada atributo.
Aula 287 - App Orçamento Pessoal - Filtrando despesas parte 1
Nesta parte vamos fazer o filtro de despesas na tela de Consulta. Os menus já estão definidos no código html.
O método pesquisarDespesas() será disparado no onclick do botão de pesquisa.
PAra iniciar criamos a função pesquisarDespesas() que irá consultar os valores preenchidos nos campos do formulário de consulta. A diferença aqui para a função cadastrarDespesa() é que aqui vamos receber os valores(value) dos campos digitados. Vamos novamente instanciar um objeto despesa que receberá como parametro os valores digitados no campo de consulta. Esse objeto criado será passado para o método pesquisar() em bd para em seguida se comunicar com o Local Storage.
Na função pesquisarDespesas() faremos a chamada do método pesquisar() através de bd.pesquisar(despesa) transportando para o método em bd os valores capturados em despesa. Esses valores encaminhados pelo objeto criado farão o filtro dos valores selecionados.
Aula 288 - Extra - Array Filter
Entendendo como fazer filtros em arrays. Primeiramente criamos um array de objetos literais. O método filter é nativo de arrays em JS e é semelhante ao forEach(). Ele necessita de uma função de callback que fará o teste lógico no array retornando sempre um array igual ou menor que o original. Desse modo se tivermos um retorno true o array será igual ao original e se tivermos um retorno false será retornado um array vazio.
Quando utilizamos o filter() a função de callback terá um parametro que será utilizado para verificar junto ao atributo se a condição é verdadeira ou falsa e retornará portanto apenas os objetos que tenham a resposta do teste lógico true.
Podemos ainda aplicar vários filter() diferentes simplesmente adicionanado os novos filtros em seguida da notação do primeiro.
A sintaxe do filter é a seguinte:

nome_do_array.filter(function(param) { return param.nome_do_atributo teste_lógico valor_a_ser_filtrado}).filter(function(param) {return lógica_do_segundo_filtro})

Podemos ainda utilizar arrow functions

nome_do_array.filter((param) => { return param.nome_do_atributo teste_lógico valor_a_ser_filtrado}).filter((param) => {return lógica_do_segundo_filtro})

E ainda suprimir o return e as { } pois temos apenas um valor de teste:

nome_do_array.filter((param) => param.nome_do_atributo teste_lógico valor_a_ser_filtrado).filter((param) => lógica_do_segundo_filtro)

Aula 289 - App Orçamento Pessoal - Filtrando despesas parte 2
Para fazer o filtro das despesas vamos partir do método de listar despesas recuperarTodosRegistros() pois ele já vai ter feito a leitura do Local Storage. Dessa forma ao invés de fazermos um novo código para verificar os dados contidos lá, vamos aproveitar a rotina e apenas aplicar um filtro.
Para isso criamos uma variável no método pesquisar() que receberá a lista gerada em recuperarTodosRegistros(). O método pesquisar() recebe como parâmetro os valores recebidos na função pesquisarDespesa(). A comparação destes dois elementos que será resposável pelo filtro.
O primeiro filtro feito é o de ano. Utilizamos o conceito aprendido acima, passando como parametro para a função de callback o ano do Array criado aqui e comparando com o valor recebido pelo método.
Repetimos esse instrução para cada item da tabela mas antes devemos criar um teste lógico para verificar se o atributo não está vazio. Caso o valor daquele campo esteja vazio devemos ignorá-lo e testar o próximo campo.
Esse filtro por enquanto está 'case sensitive' e não está ignorando números '0' a esquerda. Caso não seja ajustado isso durante as próximas aulas é algom que posso implementar.
Aula 290 - App Orçamento Pessoal - Filtrando despesas parte 3
Uma vez que já temos um novo array com o filtro aplicado que é retornado pelo método pesquisar(), aproveitamos esse array e aplicamos a ele a mesma construção aplicada na função carregaListaDespesa(), criando uma tabela com os dados desse novo array. Entretanto essa solução apenas insere os dados na sequencia dos dados já apresentados. Para solucionar isso devemos limpar o conteúdo das tags da tabela. Fazemos isso passando um valor ' ' para o atributo innerHTML do elemento.
Em seguida foi feita uma refatoração para retirar a repetição do código de criação de tabelas nas funções carregaListaDespesas() e pesquisarDespesas(). NO exemplo da aula foi realizada uma lógica aproveitando a construção em carregaListaDespesa(). Eu achei um pouco confuso e achei melhor manter no modo que eu fiz, construindo uma função separada para a construção da tabela de retorno. Para entender o modo que foi feito, assistir a aula novamente, mas acho que não será necessário (a menos que apareça algum problema na execução do meu método).
Aula 291 - App Orçamento Pessoal - Removendo despesas e considerações finais
Para criar o botão de exclusão de despesas utilizaremos a função de criação da tabela (no meu caso a função criaTabela()).
Para isso criamos uma variável para criar o botão que receberá a propriedade document.crateElement('button'). Essa variável será incluída na tabela atravé do comando linha.insertCell().append(nome_da_variável).
Feito isso já temos o botão criado. Em seguida aplicamos os estilos do Bootstrap através de nome_da_variável.className = 'btn btn-danger' para definir a cor e o formato do botão e inserimos como conteúdo da tag <button> criada o valor nome_da_variável.innerHTML = '' que inclui um ícone do Font Awesome.
O próximo passo é fazer a lógica para o botão. Aplicamos a proipriedade >nome_da_variável.onclick = e vamos criar uma função para executar a exclusão da despesa.
Para que possamos saber qual item foi clicado em Local Storage precisamos criar um indice no objeto que o identifique individulamente em relação aos demais itens já criados. Para isso não precisamos criar um novo atributo na classe construtora apenas criar o novo atributo no método que insere os dados no array de despesas (recuperarTodosRegistros).
Com esse numero no array podemos criar para cada tag <button> uma 'id' com o número correspondente a linha que ele se referencia.
Em seguida criamos um método na classe bd para remover o item de Local Storage. Esse método irá executar a função localStorage.removeItem() recebendo como parametro o número do 'id' selecionado pelo botão de remoção. Como no exemplo as ids dos botões de remoção foram criadas com um prefixo utilizamos o a propriedade replace() para remover o prefixo adicionado. Finalizando chamamos o método criado remover() com o número do id como parametro. Por fim, precisamos recarregar a página para atualizar a tabela apresentada. Fiz isso chamando o método carregaListaDespesas() novamente para atualizar a tabela. O professor utilizou o método de manipulação do DOM window.location.reload().