0% acharam este documento útil (0 voto)
10 visualizações123 páginas

Apostila PP - Módulo 04

O módulo 04 aborda conceitos intermediários de JavaScript, focando em funções, incluindo declarações, expressões e arrow functions. Também introduz Factory Functions e Constructor Functions, explicando como criar e manipular objetos, além de discutir Prototypes e Classes como formas de estruturar código. O aprendizado é complementado com exemplos práticos e exercícios para reforçar a compreensão dos conceitos.
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
10 visualizações123 páginas

Apostila PP - Módulo 04

O módulo 04 aborda conceitos intermediários de JavaScript, focando em funções, incluindo declarações, expressões e arrow functions. Também introduz Factory Functions e Constructor Functions, explicando como criar e manipular objetos, além de discutir Prototypes e Classes como formas de estruturar código. O aprendizado é complementado com exemplos práticos e exercícios para reforçar a compreensão dos conceitos.
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 123

MÓDULO 04

JAVASCRIPT INTERMEDIÁRIO
Nesse módulo começaremos a estudar mais a fundo a linguagem JavaScript.
Como aprendemos lógica de programação já utilizando essa linguagem,
muitos conceitos aprendidos no módulo anterior irão ser aproveitados
nesse módulo.

FUNCTION DECLARATION, FUNCTION EXPRESSION E ARROW FUNCTION


Funções são extremamente importantes dentro de qualquer linguagem,
especialmente JavaScript. Aqui vamos aprender sobre esses três tipos de
função. Começando pela mais comum, que já vimos anteriormente. Mas
antes de tudo, crie (caso ainda não tenha feito isso) o ambiente necessário
para praticarmos:

Crie uma nova pasta com o nome Modulo04 e abra ela no seu VS Code. Após
isso crie os arquivos index.html e script.js. Não esqueça de criar também
uma estrutura inicial no html e fazer o link com o arquivo script.js. Feito isso,
vamos para o código:

1
Essa é a forma mais comum de declarar uma função e chama-la. Primeiro
declaramos com function, depois damos um nome para essa função
seguido de parênteses: teste( ). Abrimos chaves { } e dentro de chaves
colocamos o bloco de códigos que deverá ser executado quando essa
função for chamada. Logo abaixo estamos chamando a função pelo nome e
estamos executando ela com ( ) parênteses. Para visualizar a saída no
console, abrimos o arquivo index.html no navegador e executar o atalho ctrl
+ shift + i, para visualizar o console.

Também podemos passar parâmetros na declaração de função, e


argumentos para esses parâmetros quando a função for chamada.

Nesse caso, nome está sendo passado como parâmetro dessa função, o
valor que será recebido por meio desse parâmetro será exibido na função
console.log( ) e quando a função é chamada, a string ‘Paulo’ está sendo
passada como argumento desse parâmetro. O resultado no console é:

2
Até aqui nós já aprendemos e praticamos. Não há segredo, certo? Agora
veremos como é a sintaxe da function expression. Vou deixar essa primeira
função comentada para não influenciar na função que criaremos a seguir.

Perceba que utilizamos uma variável para declarar esse tipo de função. A
única diferença é que estamos atribuindo a essa variável uma função
anônima, que também vimos anteriormente. Não se faz necessário dar um
nome para a função pois o nome da variável já representa essa função.
Tanto que podemos chamar essa função e executa-la abaixo pelo nome da
variável. Se abrirmos no console, veremos que o resultado é exatamente o
mesmo. Mas então por que usar uma ou outra forma? Mais para frente
veremos a aplicação prática desses tipos e porquê usar um ou outro. Da
mesma maneira, também é possível passar parâmetros e argumentos da
mesma forma.

3
É muito comum também usarmos juntamente com a function expression,
um tipo de função anônima chamado de arrow function. A diferença é que,
ao usar arrow function, nós não usamos a palavra function para dizer que
aquilo é uma função, nós utilizamos => que nada mais é do que o símbolo
de igual =, junto com o símbolo de maior que >. Arrow traduzido é flecha.
Por isso, chama-se arrow function, que na tradução literal seria: função
flecha. Note que o desenho realmente parece o de uma flecha. Como seria
usar arrow function na prática? Dessa forma:

Basta abrir parênteses ( ) e usar o símbolo de arrow function =>


É uma forma mais simples e moderna de se usar uma função anônima como
valor de uma variável. Arrow function será muito utilizada nos próximos
módulos, então fixe bem a sua sintaxe. Também podemos usar outra sintaxe
para arrow functions, que é colocando tudo na mesma linha, sem a
necessidade de abrir chaves { }.

Mas essa forma é mais indicada quando temos apenas uma tarefa a ser
executada. Geralmente uma função tem varias tarefas a serem executadas,
então para melhor organização no código, é interessante abrir chaves e
colocar as tarefas uma abaixo da outra. Mas isso aqui é apenas para
demonstrar que também é possível colocar na mesma linha.

4
FACTORY FUNCTION
Nesse módulo, estudaremos bastante sobre funções. De fato, elas são muito
importantes. O próximo tipo de função que veremos é a Factory Function.
Basicamente, é uma função que retorna um objeto quando ela é executada.
Vamos criar o seguinte exemplo:

Nome que temos uma variável chamada factoryFunction, cujo valor é uma
função anônima (arrow function) que retorna (return) um objeto com dois
métodos: logou e deslogou. Chamamos de métodos quando as chaves do
objeto tem funções como valor. Caso tivessem qualquer outro tipo de dado
como valor, chamaríamos de propriedades. Tal função espera receber o
parâmetro name quando for chamada. Por ser uma função que retorna um
objeto, podemos dizer que é uma Factory Function.
Agora como fica a execução dessa função? Ela vai exibir o alert dizendo que
o usuário logou ou vai exibir o alert dizendo que o usuário deslogou? Ou os
dois ao mesmo tempo? Bom, isso vai depender de como nós vamos chamar
a função. Veja os seguintes exemplos:

Observe que a função está sendo chamada e passando a string ‘Paulo’ como
argumento do parâmetro name. Até aqui sem novidades.
5
Como estamos lidando com uma Factory Function, é possível acessar os
métodos e propriedades do seu retorno por meio do dot notation. Nesse
exemplo, temos dois métodos: logou e deslogou. Então, basta colocarmos
um “ . “ ponto seguido do nome do método que desejamos executar:

Não podemos esquecer de também executar o método usando parênteses


( ). Salve as alterações no seu VS Code e atualize a página no navegador para
ver o resultado.

Exatamente como esperado. Caso queira acessar o outro método


(deslogou), basta fazer o mesmo processo.

Veja agora no navegador qual mensagem aparece.

6
Nós conseguimos acessar os métodos e propriedades retornamos pela
Factory Function. A princípio, só estamos exibindo uma mensagem. Mas,
em aplicações mais complexas, isso poderá ter uma utilidade real.

CONSTRUCTOR FUNCTIONS
Agora vamos estudar sobre as Constructor Functions. Elas são funções
capazes de construir novos objetos com métodos e propriedades. Mas qual
seria a diferença desse tipo de função em relação as Factory Functions.
Bom, quando estamos usando Factory Functions, temos o retorno de
apenas um objeto. Através das Constructor Functions, podemos criar vários
outros objetos a partir do objeto original, como os mesmos métodos e
propriedades do primeiro ou até com outros adicionais. Veremos melhor na
prática. Primeiramente vamos criar um exemplo da forma ERRADA de se
fazer, pois assim ficará mais claro o objetivo de usar uma Constructor
Function.

Criamos um objeto com o nome pessoa que possui duas chaves: name
(nome) e age (idade). As propriedades dessas chaves estão vazias
inicialmente.

7
Vamos agora criar outros objetos a partir desse original.

Dessa forma, é como se estivéssemos criando um novo objeto a partir do


original e atribuindo valores às chaves name e age. Só que existe um
problema nisso. Vamos entender melhor esse problema indo no nosso
console, no navegador.

8
Quando abrimos o console no navegador, é possível digitar nesse campo
para acessar variáveis do nosso código. Então digite: pessoa1 e tecle ENTER
nesse campo, dessa forma:

Veja que o objeto pessoa1 apareceu ali corretamente com os valores que
atribuímos para as chaves. Então deu certo? Criamos um novo objeto? NÃO.
Na linha debaixo digite apenas pessoa, depois tecle ENTER.

Veja que o objeto original também foi alterado. Não é isso que queremos.
Caso formos criar um outro objeto chamado pessoa2, por exemplo, ele
também alteraria os valores dos anteriores. Confira:

9
Agora pesquise pelos três objetos criados: pessoa, pessoa1 e pessoa2

Todos estão com os mesmos valores.


Logo, esse foi um exemplo do que não se deve fazer. Foi necessário fazer dar
errado para mostrar toda a utilidade da Constructor Function. Vamos
apagar tudo e começar do jeito certo.

A primeira coisa é que Constructor Functions são escritas com a primeira


letra maiúscula, diferentemente do padrão usado em outros casos. A
segunda coisa a se notar é a palavra this, o que ela faz? A palavra this é
usada para se referir diretamente ao objeto atual em que o código está
sendo inserido. Futuramente, this será necessário para definir as
propriedades das chaves name e age.

10
Agora vamos criar um novo objeto a partir desse original e atribuir novas
propriedades para as suas chaves.

Utilizamos a palavra new para indicar que estamos criando uma nova
instância de um determinado objeto. No nosso exemplo, objeto é o Pessoa.
Observe que a função está sendo executada também.

Agora podemos atribuir novas propriedades para as chaves name e age.


Para ampliar nosso exemplo, vamos criar mais um objeto e vamos chama-
lo de pessoa2.

11
Salve as alterações e atualize a página no navegador. Após isso pesquise por
pessoa1 e tecle ENTER. Na linha debaixo faça o mesmo com pessoa2.

Exatamente o resultado que queremos. Temos objetos distintos, com


propriedades distintas, sem alterar o modelo original. Por curiosidade você
pode pesquisar também por Pessoa (primeira letra maiúscula) e constatar
que o modelo original não foi alterado. Ainda podemos melhorar mais esse
código. Como estamos trabalhando com uma função, podemos estabelecer
parâmetros e enviar argumentos para esses parâmetros na execução.
Ficaria assim:

Agora estamos colocando name e age como parâmetros esperados na


declaração da função. Tais valores, quando recebidos na execução, são
aproveitados como propriedades do objeto original.
No momento da execução, basta passar os devidos argumentos para esses
dois parâmetro que vamos obter exatamente o mesmo resultado, só que
com um código mais limpo e organizado.

12
PROTOTYPES
Prototypes (protótipos) são diretamente ligados à funções. É possível criar
novos métodos e propriedades dentro de um prototype, uma vez que eles
são objetos dentro de funções. Seguindo praticamente a mesma sintaxe já
vista anteriormente, vamos usar o exemplo de um jogo:

Agora temos dois métodos (funções) que são atribuídos às chaves pulou e
deitou. Esses métodos foram criados diretamente na função Game. Como
criar um novo método dentro do prototype da função?

Primeiro chamamos a função pelo nome e acrescentamos um `.prototype`


seguido de um `.correu` que seria o nome do novo método que estamos
criando. Feito isso, basta atribuir o método em si, que no nosso exemplo é
um alert que exibe a mensagem “O personagem correu”. Assim, já criamos
um novo método dentro da nossa função Game. Bom, se formos criar um
novo objeto utilizando o conceito de constructor function aprendido
anteriormente, teremos:

13
Vamos visualizar essa variável no console adicionando um console.log( ) e
passando essa variável dentro. Dessa forma:

Abra o console no seu navegador.

Note que temos um objeto. Clique na setinha para abri-lo.

Veja que temos deitou, pulou e o prototype. Os dois primeiros métodos


foram criados diretamente na função. O terceiro método foi criado dentro
do objeto prototype. Clique na setinha de prototype para vê-lo:

14
O método correu aparece aqui como o esperado.
Agora que criamos um novo objeto utilizando a função construtora,
podemos ter acesso aos mesmos métodos e propriedades, tanto os criados
diretamente na função, quanto aos herdados no prototype, de modo que
conseguimos acessá-los e executá-los. Aí mesmo no console digite o nome
da variável que usamos para criar um novo objeto (novoJogo) seguido da
execução de um dos métodos. Assim:

Após digitar, tecle ENTER para que o método seja executado.

Faça o mesmo com os outros métodos e comprove.

15
Estamos começando a entender mais um conceito importante em
JavaScript, que é o conceito de herança. Assim como criamos funções
construtoras para os exemplos anteriores, em JavaScript temos vários
construtores nativos da linguagem, a saber:
➢ Construtor de strings – String
➢ Contrutor de objetos – Object
➢ Construtor de arrays – Array
Dentre outros. Podemos visualizar um pouco desses construtores lá no
console do navegador. Digite no console String (assim mesmo com letra
maiúscula no começo) e tecle ENTER.

Esse “ f “ é de função, pois nada mais é do que uma função construtora de


strings. O mesmo você pode fazer com os outros citados. Os métodos
desses construtores nativos são costumeiramente usados nas nossas
aplicações. Por exemplo, o método toUpperCase é um método que é
herdado do construtor de strings. Esse método faz com que os caracteres
de uma string fiquem todos em maiúsculo. Vamos ver na prática:

Se criarmos uma variável cujo valor é uma string, tal dado herda os métodos
e propriedades do construtor de strings, então podemos chamar o nome da
variável e, usando dot notation (ponto), podemos chamar e executar o
método toUpperCase. Salve no VS Code e atualize a página no navegador:

16
Apesar da string ter caracteres minúsculos inicialmente, após a execução do
método ele transforma os caracteres em maiúsculo.
Logo, mesmo que nós não criamos esse método, nós herdamos ele por meio
do construtor de strings, que é nativo da linguagem.
Vamos usar bastante construtores no nosso dia-a-dia e conforme vamos
evoluindo, iremos criar novos exemplos. É importante que você saiba que
existem vários construtores nativos e que cada construtor nativo possui
seus próprios métodos e propriedades (e são muitos, inclusive).

CLASSES
A seguir começaremos a estudar sobre classes, que é uma outra maneira de
escrever funções construtoras. Como podemos utilizar classes?

Devemos usar a palavra reservada class seguida do nome da classe. Ao


nomear classes, o padrão de escrita que usamos é o pascal case, que
consiste na primeira letra ser maiúscula. Outro detalhe, é que não
precisamos atribuir um valor usando o sinal de igual = . Ao invés disso,
abrimos chaves diretamente. Feito isso, vamos adicionar mais uma coisa.

Dentro da classe, adicionamos um método padrão chamado de constructor.

17
Como ele é um método, também pode ter parâmetros e receber
argumentos. Iremos utilizar o this, já visto anteriormente, para acessar
esses valores dentro da classe.

Dois parâmetros foram passados para o método constructor: name e age.


Logo abaixo, this.name e this.age representam as chaves desse objeto que
por sua vez tem como valor os valores recebidos nos parâmetros. Também
podemos criar novas propriedades usando this e atribuir valores à elas
normalmente. Por exemplo:

A diferença em relação ao que vimos anteriormente é que ao invés de


criarmos propriedades diretamente dentro da função, estamos criando
dentro do método constructor, que fica dentro da classe.
Caso queiramos criar um novo método dentro dessa classe, devemos cria-
lo também dentro do método constructor? Não. Podemos fazer isso
diretamente na classe. Veja a seguir.

18
Pronto. Bem simples. Apenas damos um nome ao método (andou) e
colocamos parênteses, justamente para indicar que é um método. Dentro
de chaves passamos quais tarefas aquele método deverá executar quando
ele for chamado. A vantagem de usar dessa forma é que podemos
aproveitar os valores das propriedades criadas em constructor nesse novo
método andou( ). Veja:

Aqui usamos a template string para concatenar e passamos a propriedade


name, criada dentro de constructor, cujo valor será recebido por meio do
respectivo parâmetro.

19
Em relação a criar uma nova classe a partir da original, a forma é a mesma,
não há diferença. Mas vamos recapitular:

Declaramos uma variável e atribuímos uma nova instancia da classe Pessoa,


passando como argumentos os valores que são esperamos em contructor.
Veja o código como um todo:

Podemos testar tudo isso. Salve essas alterações no VS Code e atualize a


página no seu navegador. Após isso, abra o console no navegador.

Se digitarmos no console pessoa1 e teclarmos ENTER, teremos o objeto


criado com as suas devidas propriedades e os valores são exatamente os
esperados. Se clicarmos na setinha de Pessoa, poderemos visualizar melhor
seu conteúdo:

20
Podemos clicar também na setinha de prototype e ver que o método que
criamos está lá.

Podemos executar esse método se quisermos. Digite no console


pessoa1.andou() e tecle ENTER.

O alert foi exibido como esperávamos.

21
Existe uma forma de impedir que determinado método de uma classe seja
acessado por um objeto criado a partir dela. Podemos fazer isso usando a
palavra padrão static.

Se colocarmos a palavra static antes do nome do método, estamos


impossibilitando-o de ser acessado de fora por um objeto criado a partir da
classe original onde tal método foi criado. Então se salvarmos no VS Code e
atualizarmos a página no navegador, veremos que esse método andou( )
não estará mais disponível.

Veja que deu erro. Eu só vou conseguir acessar esse método a partir da
classe original, que é Pessoa, veja:

Foi exibido no alert dessa forma pois agora não existem argumentos sendo
passados. Lembre que passamos argumentos em pessoa1.

22
Outra coisa que podemos fazer com classes, é estender uma classe para
outra, como se a segunda fosse a extensão da primeira, de modo que a
classe que foi estendida tem acesso aos mesmos métodos e propriedades
que a classe que estendeu tem.

Aqui criamos uma nova classe chamada Animal que é uma extensão da
classe Pessoa. Essa nova classe também tem um constructor que cria uma
propriedade chamada especie. Também adicionamos o método dormiu( ) a
essa classe. Agora, temos acesso aos mesmos métodos e propriedades da
classe Pessoa. Quando usamos uma classe estendida, pode acontecer de
termos dois métodos com o mesmo nome nas duas classes. Como podemos
diferenciá-los na hora de executar um método? Faremos isso usando outra
palavra reservada que é a palavra super.
Vamos criar um método dentro da classe Animal com o mesmo nome de
um método presente na classe Pessoa.

23
Quando usamos o super( ), que também é um método, estamos falando
diretamente com os métodos disponíveis na classe que estendeu, ou seja,
estamos dentro da classe Animal, chamando um método que está dentro
da classe Pessoa.
Também podemos usar o super para estender parâmetros para classes
estendidas.

24
Aqui usamos o super na classe construtora esperando o parâmetro patas.
Na classe estendida, passamos esse mesmo parâmetro dentro de
constructor. Assim conseguimos estender também os parâmetros de uma
classe para outra.

25
DESESTRUTURAÇÃO
Dando continuidade aos nossos estudos, aprenderemos sobre
desestruturação, que nada mais é do que uma nova forma de acessar
propriedades e métodos de um objeto e também uma nova maneira de ter
acesso aos itens de um array. Começaremos criando um objeto, o qual
daremos o nome de pessoa.

Até aqui temos usado dot notation para acessar propriedades e métodos
de determinado objeto, que seria dessa forma:

Chamando o nome do objeto, colocando um ponto (dot) e a propriedade


que queremos visualizar. Até aqui temos feito dessa forma. Mas também
existe uma outra forma de acessar propriedades e métodos sem precisar
usar dot notation. Faremos isso por meio da desestruturação. De que
forma?

26
Criando uma variável e passando um conjunto de chaves vazio como se
fosse o nome dessa variável. Então, atribuímos a essa variável o objeto que
pretendemos acessar, que no nosso exemplo, é o objeto pessoa.

Feito isso, basta colocar dentro de chaves qual propriedade eu quero extrair
desse objeto, por exemplo, a propriedade cidade. Se dermos um console.log
em cidade, veremos no console o seguinte:

Teremos o valor que está atribuído a propriedade cidade, que é Fortaleza.


Podemos fazer isso com mais de uma chave também:

27
E como faremos caso tenhamos um objeto dentro de outro objeto? Ou seja,
caso uma das propriedades do objeto possua como valor também um
objeto, como acessá-lo? Vamos criar esse exemplo:

Mudamos um pouco a estrutura desse objeto. Agora temos uma


propriedade chamada endereço, que tem o valor equivalente a um objeto
que possui outras duas propriedades, cidade e estado. Como podemos
acessar essas propriedades que estão dentro da propriedade endereço?

Ao invés de atribuir a essa variável o objeto como um todo, atribuímos


apenas a propriedade a qual queremos “falar” diretamente. Então, se
queremos acessar propriedades que estão dentro de endereço, então
vamos atribuir a variável que está desestruturando pessoa.endereço.
Mas existe uma forma de fazer o mesmo só que sem precisar usar dot
notation? SIM.

28
Observe que estamos atribuindo como valor o objeto pessoa como um todo
sem usar dot notation. Só que ao invés de desestruturarmos o objeto pessoa
dentro de chaves, estamos desestruturando a determinada propriedade
contida dentro do objeto pessoa, que é endereço, extraindo dela apenas o
que queremos, que é cidade. Veja no console.

E caso tentemos acessar uma propriedade que não está presente dentro do
objeto que estamos desestruturando? Vamos tentar?

Por padrão, no nosso console aparecerá undefined.

Podemos estabelecer uma valor padrão para caso não exista determinada
propriedade dentro de um objeto. Por exemplo:

29
Agora estamos dizendo que caso não exista uma propriedade chamada
altura dentro do objeto pessoa, o valor padrão para altura será 1.72.

E se caso adicionarmos essa propriedade inexistente?

Dessa forma o valor padrão de 1.72 será ignorado e no console teremos:

Bom, já vimos o suficiente por hora sobre desestruturação de objetos.


Vamos ver a seguir sobre desestruturação de arrays.

30
Não muda muita coisa em relação a desestruturação de objetos. O que
basicamente muda, é que na desestruturação de arrays, não vamos pegar
os valores através dos nomes das propriedades ou métodos, e sim pela
posição na lista (index). Em arrays, não temos métodos e propriedades, o
que temos são posições numeradas dentro do array chamadas de index que
traduzido é o mesmo que índice. Vamos criar uma array que representa uma
lista de carros.

Para acessar determinado valor, bastaria chamar o nome do array e colocar


a posição que queremos visualizar entre colchetes, por exemplo:

O resultado que teríamos seria: hb20. Lembrando que a posição 0 equivale


ao primeiro item do array.
Como poderíamos fazer a desestruturação a fim de não precisarmos ficar
passando o index? Veja abaixo:

Criamos a variável e abrimos colchetes, como se fosse o nome da variável,


bem parecido com a forma que fizemos com objeto. Depois atribuímos
como valor dessa variável o array em si, que é carros.
Mas dentro de colchetes temos primeiroCarro, de onde vem esse nome?
Lembra do conceito de parâmetros e argumentos de uma função? O nome
do parâmetro tanto faz, é você quem escolhe, pode ser qualquer um,

31
embora seja recomendado colocar nomes que façam sentido. O que será
levado em consideração é a ordem que colocamos. Então, o primeiro nome
que colocamos dentro de colchetes equivale a primeira posição do array
([0]), o segundo nome equivalerá a segunda posição ([1]) e assim por diante.
Veja:

Dessa forma, o nome segundoCarro resultará no valor hilux, que ocupa a


segunda posição na lista carros. Veja no console:

Mas vamos inverter pra que você entenda melhor:

Se você for no console verá que o retorno é hilux. Apesar do nome que
colocamos ser primeiroCarro, ele é o segundo nome na ordem dessa
variável. Logo, ele terá como valor o que está na segunda posição do array.
Isso é só para demonstrar que o nome em si “tanto faz”, o importante e
colocar na ordem correta, assim como fazemos com parâmetros e
argumentos de uma função.

32
Então eu preciso escrever um nome para cada posição na lista? E se for um
array com 10 itens? Bom, não precisamos escrever um nome
necessariamente, embora isso seja bom para organização do código. Basta
adicionar uma vírgula, e isso já será interpretado como um item. Veja:

Aqui foram adicionadas duas vírgulas que representam os dois primeiros


itens do array. Na terceira posição da ordem, colocamos o nome de carro3
para representar o item presente na posição 3 do array. O retorno é:

Exatamente! Sobre desestruturação, é isso que precisamos saber por


enquanto.

REST E SPREAD
Nesse momento, começaremos a aprender sobre Rest e Spread.
Primeiramente, estudaremos o Rest. Usar o Rest nos permitirá reunir todos
os argumentos de uma determinada função em um único array, deixando
assim nosso código mais limpo e organizado. Começaremos nosso primeiro
exemplo criando uma função que espera alguns parâmetros e em seguida
iremos executar essa função passando argumentos.

33
Essa função espera receber siglas de estados do Brasil. Colocamos E1, E2,
E3 apenas para encurtar um pouco, mas isso não seria recomendado na
prática, afinal, os parâmetros devem ser bem explicados e coerentes em
relação aos dados que esperam, facilitando a leitura. Mas para fins de
exemplo usaremos assim. Na execução da função podemos ver que estão
sendo passados argumentos para cada um dos parâmetros. Ali no
console.log() você pode ir conferindo valor por valor e verá que estão sendo
imprimidos no console corretamente. Por exemplo, ali estamos dando um
console.log() em E1. Visualizando no navegador:

Agora veremos o poder do rest. Vamos transformar todos esses parâmetros


em um único array?

34
Ao invés de colocar parâmetro por parâmetro separados por vírgulas,
usamos a seguinte sintaxe: ...nomeDoArray, ou seja, três pontos seguido do
nome do array, que no caso colocamos o mesmo nome da função – estados.
Se dermos um console.log(estados) veremos no console do navegador:

Todos os argumentos recebidos foram colocados dentro de um único array,


isso deixa o nosso código bem mais limpo quando se trata de uma função
que possui muitos parâmetros. Caso queiramos visualizar apenas um desses
argumentos individualmente, basta adicionar o index ao lado do nome do
array, dessa forma:

Estamos imprimindo no console a posição 2 do array estados. O argumento


que está na posição 2 é ‘SP’. Se você visualizar no console verá exatamente
esse valor.

35
Então, usando Rest, podemos transformar os vários parâmetros em um
único array, que por sua vez receberá dentro dele todos os argumentos
enviados na execução da função de uma só vez.
Também é possível adicionar outros parâmetros depois de usar Rest.

Nesse caso, o primeiro parâmetro espera receber o primeiro argumento,


que é ‘CE’. Os demais argumentos serão inseridos dentro do array estados.
Lembrando que esse é um recurso muito interessante, mas não deve ser
usado a todo momento. Existem situações específicas onde será
conveniente usar o Rest.

Agora, estudaremos sobre o Spread. Basicamente, o Spread permitirá pegar


todos os itens de um array e espalhá-los em determinado lugar. Vamos
começar nosso exemplo criando dois arrays, um para carros altos e outro
para carros baixos.

Agora vamos criar um terceiro array chamado carros e usaremos o Spread


para espalhar os itens dos arrays anteriores dentro dele.

36
Assim como Rest, o Spread também é representado por três pontos seguido
do nome do array. Vamos dar um console.log(carros) para ver seu conteúdo.

No navegador:

Então, através do Spread, conseguimos jogar todos os itens de uma


determinada lista em outra lista, facilitando o processo e deixando o código
mais limpo e organizado.
Da mesma forma, também podemos fazer isso com objetos.

Criamos dois objetos. Agora vamos usar o Spread para lançar os dados
desses dois objetos em um terceiro objeto que chamaremos de dados.

37
Agora o objeto dados contém todas as chaves e valores dos dois objetos
criados anteriormente. Vamos dar um console.log(dados) e ver no
navegador:

38
Lembrando que também podemos adicionar novos itens além dos Spreads.

Então agora que já aprendemos como funcionam Rest e Spread, podemos


dar continuidade.
STRING
A seguir, veremos os principais métodos e propriedades do construtor de
strings. Para tanto, criaremos duas variáveis const cujos valores serão
strings.

Começando pela propriedade length. Essa propriedade retorna a


quantidade de caracteres de uma string, considerando também os espaços
como caracteres.

Adicionando um console.log( ) podemos visualizar o retorno. Salve as


alterações no VS Code e atualize a página no navegador. Veja o que aparece
no console:

39
Se você contar, verá que a string armazenada na variável string1 tem
exatamente 20 caracteres, lembre-se de contar o espaço como um
caractere. Faça o teste também com a string2.
O próximo tópico é o método charAt( ). Esse método revela qual caractere
está na posição indicada no método. Por exemplo:

Se verificarmos no console, veremos que o caractere presente na posição 1


é o caractere i.
Imagine que cada caractere da string ocupa uma posição numérica
começando da posição 0, assim como um array. Logo, a posição 0 equivale
ao primeiro caractere da string, o J. Por isso, o caractere na posição 1 é o i.
Teste colocando no charAt( ) outras posições e veja o resultado.
O próximo método que veremos é o toLowerCase( ). Basicamente esse
método transformará todas os caracteres de uma string em minúsculos.
Perceba que na variável string1, possuímos uma string que contém alguns
caracteres maiúsculos. Vamos executar o método e visualizar no console.

40
No console:

Todos os caracteres minúsculos.


Também temos o método toUpperCase( ), que faz exatamente o contrário,
deixando todos os caracteres da string maiúsculos. Vamos fazer esse
exemplo com a string2.

Tudo maiúsculo.

41
O próximo método é o endWith( ). Esse método retorna um boolean. Ele
verifica se a string termina com o valor que foi passado dentro dele. Por
exemplo:

Aqui queremos verificar se a string armazenada na variável string1 termina


com ‘Javascript’. O retorno no console é:

Agora se colocarmos com o J minúsculo, por exemplo, o retorno será false,


pois o método levará em consideração letras maiúsculas e minúsculas.
Podemos usar o método toLowerCase aprendido anteriormente para
ajudar nessa questão.

Primeiro usamos o método toLowerCase para transformar todas as letras


da string em minúsculas, depois usamos o método endWith para verificar
se a string termina com ‘javascript’. Assim, garantimos que ambas as strings
terão somente letras minúsculas, podendo realizar uma comparação mais
acertiva. Verifique no console que o retorno é TRUE.
O próximo método é o startWith( ) que é exatamente o contrário, ele
verifica se a string começa com determinado valor.

42
Aqui estamos verificando a variável string2. O retorno será false, pois a
string2 começa com ‘de’ e não com ‘programação’.
O próximo método já é mais abrangente. O método includes( ) verifica se a
string que estamos passando dentro está presente na string verificada como
um todo. Aproveitaremos o exemplo anterior para isso.

Nesse caso o retorno será true, pois apesar de string2 não começar com
‘programação’, essa string está presente nela. Não necessariamente eu
preciso passar uma palavra inteira, pode ser parcial também. Exemplo:

O retorno aqui também será true. A string ‘ação’ não é uma palavra dentro
de string2, mas esse grupo de caracteres está presente nessa ordem, então
é true.
A seguir, veremos o método concat( ). Esse método irá unir uma string à
outra.

43
Aqui estamos unindo a string1 com a string2. O retorno no console é:

Ficaram emendadas realmente pois não há espaço nem no fim de string 1


nem no começo de string2. Esse método não é muito utilizado para
concatenar strings, existem outras formas como template string que é mais
eficiente, mas é importante ter o conhecimento.
Continuando, veremos agora o método substring( ). Esse método irá extrair
o trecho de uma string através da posição. Veja:

Observe que aqui estamos determinando um intervalo. É como se


dissemos: retorne todos os caracteres entre a posição 1 e a posição 3. O
retorno será:

Veja que o caractere na posição 3 não é retornado. Isso é porque o segundo


parâmetro do método estabelece o limite, ou seja, somente os caracteres

44
antes dessa posição serão retornados, no caso, a posição 1 e 2. Já o primeiro
parâmetro é retornado, como colocamos a posição 1 ele irá extrair o
caractere da própria posição 1 e então os demais que estão antes da posição
informada no segundo parâmetro.

Se fizermos dessa forma, ele vai retornar os caracteres nas posições de 1 a


8, por exemplo.
Também temos o método slice( ). Funciona bem parecido com o substring,
porém com a diferença de podermos passar valores negativos. Por exemplo:

Dessa forma, o método retornará os três últimos caracteres da lista, que no


caso são: ipt.
Também posso usar valores positivos. Nesse caso ele removerá os três
primeiros caracteres e retornará os restantes. Veja:

45
Agora veremos o método padStart( ). Esse método irá aumentar a string
com o caractere que passarmos. Esse método recebe dois parâmetros. O
primeiro é o número de caracteres que a nossa string deverá possuir após o
método ser executado e o segundo é qual caractere que queremos que seja
acrescentado. Por exemplo:

Nossa string1 inicialmente possui 20 caracteres. Estamos informando no


primeiro parâmetro do método que queremos que ela aumente para 25
caracteres. Logo, a diferença é de 5 caracteres. Então esses 5 caracteres
serão preenchidos com o caractere que passamos no segundo parâmetro,
ou seja, 5 pontos.

Observe que são acrescentados ao início da string.


O próximo método faz ao contrário, ou seja, adiciona os caracteres ao final
da string para completar o tamanho pretendido. O método é o padEnd( ).

46
Outro método é o split( ). Esse método irá dividir a string baseado no valor
que passarmos no parâmetro e irá construir um array a partir disso. Veja:

Aqui estamos passando que ‘ ‘ um espaço vazio será o ponto de divisão.


Logo nossa string1 será dividida em duas partes, que serão inseridas dentro
de um array em forma de itens. Veja no console:

Caso nossa string fosse maior:

Teríamos:

Por último, veremos o método replace( ). Geralmente usamos esse método


combinado com Regex (expressões regulares), mas ainda não vamos
abordar Regex por enquanto. Basicamente, o método replace irá substituir
um ou mais caracteres por outro (s).

47
Agora, todo caractere ‘a’ presente na string1 será substituído por ‘o’. No
primeiro parâmetro passamos qual caractere ou quais caracteres serão
substituídos e no segundo parâmetro passamos o caractere ou caracteres
substitutos.

Por hora vimos os principais métodos e propriedades do construtor de


strings nativo do JavaScript.

ARRAYS
A seguir veremos alguns dos principais métodos e propriedades do
construtor de array. Para iniciarmos nossos exemplos criaremos um array
contendo modelos de carros.

Mais uma vez iremos usar a função console.log( ) para visualizar o retorno
dos métodos e propriedades que estudaremos aqui.

48
Primeiro, veremos a propriedade length. Essa propriedade retorna quantos
itens determinado array contém. Então:

Novamente, salve as alterações no seu VS Code e atualize a página no


navegador. Vá até o console e veja:

Nosso array possui exatamente 5 itens.


Continuando, veremos sobre o método unshift( ). Basicamente esse método
irá adicionar um novo item no início do array.

Agora se observarmos no console:

49
Agora temos 6 itens no array. Se adicionarmos mais um console.log em
array, veremos o novo item presente.

Adicionado ao início do array.

O próximo é método shift( ), que remove o primeiro item de um array.

O primeiro item da lista é “Gol”. Ao executar o método shift, esse item é


removido do array. A seguir, imprimimos no console o array e podemos ver
que o primeiro item não não está mais presente, só os demais.

50
A primeiro console está imprimindo o item que foi removido e o segundo
mostra o array atualizado.

O próximo é o método push( ), que adiciona um item ao final de um array.

No console:

Adicionado ao fim do array.


Agora veremos o método pop( ). Esse método remove o último item do
array.

51
No console:

Removido sucesso.

Agora vamos ver o método Array.from( ). Existe uma diferença nesse


método. Aqui estamos acessando o método from( ) diretamente pelo
construtor Array. Você deve se lembrar quando estudamos sobre classes,
que estudamos sobre métodos estáticos, que não conseguimos acessar
através de itens construídos pelo construtor, como por exemplo essa
variável que chamamos de array. Só é possível acessar através do próprio
construtor. Por isso estamos chamando Array.from( ). Esse método estático
presente no construtor irá transformar algo que parece um array em um
array de verdade. Por exemplo, um Array-like, que nada mais é que um
objeto que cumpre a função de um array mas de fato não é um array.
Podemos usar o Array.from() para transforma-lo em array. Não veremos o
exemplo prático disso, até porque raramente será usado, mas vale a pena
ter o conhecimento.

Seguindo em frente veremos outro método estático que só pode ser


acessado por meio do construtor Array, o método isArray( ), que verifica se
uma variável é um array ou não e retorna um boolean.

Se olhar no console verá que o retorno é TRUE. Mas se mudarmos um


pouco, passando uma string ao invés de um array:

52
Isso certamente retornará FALSE.

O próximo método que veremos é o Join( ). Esse método transforma todos


os itens de um array em uma string. Veja:

No console:

Por padrão, esse método separa os itens com vírgula, mas eu posso passar
outro caractere como separador, por exemplo, um $.

53
Veremos agora o método concat( ), que une dois arrays.

Observe que criamos um outro array chamado array2 e passamos dentro


do método para ser concatenado com o primeiro.

No console temos os dois arrays unidos.

O próximo método também é um método estático acessado diretamente


pelo construtor Array. É o método of( ). Basta passar os valores separados
por vírgula que esse método criará um array com esses itens.

Existem outras formas de criar um array, veja a seguir.

54
Usando new Array( )

Ou simplesmente usando o construtor Array.

O próximo método é o includes( ). Verifica se determinado item está


presente dentro do array e retorna um boolean.

Esse caso retornará um FALSE.


Continuando, veremos o método sort( ). Esse método coloca um array em
ordem crescente. Funciona com arrays numéricos.

55
Mas tome cuidado. Se você tiver números com duas casas, um 23 por
exemplo, o método sort( ) não leva em consideração o número como um
todo e sim só a primeira casa, veja.

23 é maior que 5, no entando ele aparece antes pois no o primeiro é levado


em conta, no caso o 2. Existe uma forma de resolver isso, mas não veremos
agora. Futuramente aprenderemos.

O próximo método é o reverse( ). Como o nome já pressupõe, esse método


coloca os itens de um array de trás para frente.

56
O próximo método é o indexOf( ). Esse método procura no array o item que
nós passamos como argumento e retorna a primeira posição desse item no
array.

Note que apesar de haverem outros itens com esse mesmo valor, o método
retorna a primeira posição encontrada, no caso a posição 0 que equivale ao
primeiro item da lista.

57
Por último, veremos o lastIndexOf( ). Esse método retorna a última posição
de determinado valor. Faremos usando o mesmo valor de antes.

O último está na posição 4.


Por hora, é o que precisamos saber sobre métodos e propriedades do
construtor Array.

ARRAY E ITERADORES
Daremos continuidade nos estudos sobre arrays aprendendo sobre
métodos iteradores. Começaremos a construir nossos exemplos criando
dois arrays, um sendo uma lista de alimentos e outro sendo uma lista de
preços.

Antes de tudo, iteradores são métodos de repetição ou se preferir, loopings.


Um determinado bloco de códigos será executado repetidamente a medida

58
que o array é percorrido item a item pelo iterador. Veremos melhor na
prática.
O primeiro método que veremos é o forEach( ). Esse método espera receber
naquilo que chamamos de call-back, três argumentos. Esses argumentos
são: valor, index e array. Valor representa o item da lista. Index é a posição
atual da iteração e array é o array completo. Exemplo:

O método invoca uma função de call-back onde são recebidos esses


argumentos. O método está iterando com o nosso array estoque. Como
nosso array possui 6 itens, ao todo serão 6 iterações, uma para cada item.
Para cada iteração a função console.log( valor ) será executada uma vez, ao
seja, essa função será executada 6 vezes ao todo. Lembrando que esse bloco
de códigos pode conter muito mais coisas do que um simples console.log(
).

Ao atualizar a página e verificar no console do navegador, vemos que todas


as 6 funções foram executadas e que em cada uma delas foi impresso no

59
console o valor que estava sendo iterado no momento. Observe que o
último saiu em branco pois o último item da lista é uma string vazia.

Agora adicionamos também o index. Para cada iteração com o array será
impresso no console o valor e a sua posição. Veja:

Exatamente. Agora vamos adicionar o ultimo argumento recebido, o array.

Veja no console.

60
Para cada iteração, o array completo foi impresso no console. Mas para que?
Esse bloco de códigos que é executado a cada iteração pode conter
alterações no array. Então, essa seria uma forma de ver o array atualizado a
cada iteração. Um exemplo:

Aqui estamos usando um método aprendido anteriormente, o método


push( ), que adiciona o item passado ao final de um array. Para cada
iteração, o item “carne” é adicionado e o array completo é impresso no
console. Perceba que estamos usando o próprio parâmetro array para
manipula-lo ao invés de chamar estoque.push( ) (funcionaria também), pois
o argumento recebido já representa o array em si, portanto não há
necessidade de chamar novamente pelo nome da variável. Veja:

61
Observe que a cada iteração o array atualizado vai sendo impresso.
Lembrando que estamos iterando com um array de strings, mas poderia ser
um array de qualquer tipo de dado, objetos, números, etc.

Vamos prosseguir estudando o método map( ). Ele é bem parecido com o


forEach( ). A diferença é que o forEach( ) não tem retorno, já o map( ) sim.
A vantagem de ter um retorno do call-back é poder ter um novo array a
partir da execução do método, podendo armazenar tudo em uma variável.

Aqui criamos uma variável chamada retornoMap que recebe a execução do


método map( ) sobre o array estoque. Para cada iteração está sendo
construída uma template string contendo o valor e o index de cada iteração.
Vejamos o resultado disso no console.

62
No console pesquise por retornoMap e tecle ENTER.

Veja que agora temos um novo array onde cada item é o valor e o index de
cada item do array anterior. Não vamos usar esse método para construir
novos arrays dessa forma, mas esse exemplo serve apenas para mostrar a
capacidade do método map( ) ter um retorno.

O próximo método é o reduce( ). Ele também é bem parecido com o forEach


e com o map, porém a diferença é que ele tem um parâmetro a mais no call-
back.

Vamos iterar com a array preços.

63
Você deve ter notado que o call-back possui o parâmetro acc. Esse
parâmetro é chamado de acumulador. Estamos usando o exemplo de preços
pois esse contexto destaca bem a utilidade de se ter um acumulador.
Imagine um sistema e-commerce onde você pode ir adicionando produtos
ao seu carrinho. Inicialmente, o valor da compra será 0. Tem que haver um
valor inicial ali, então coloca-se 0. A medida que os produtos vao sendo
adicionados o valor do produto é somado ao valor inicial. Logo, o primeiro
produto soma com 0. Imagine que o valor do produto seja 5,00, somado
com 0 da 5,00 mesmo. Só que o próximo produto não será somado com 0 e
sim com os 5,00 que já estão lá. Então, se o segundo produto for 7,00, será
somado com 5,00 que dará 12,00 e assim por diante. Esse valor inicial e que
depois vai somando é o acumulador.

No nosso método, estamos determinado aqui o valor zero como


acumulador inicialmente. O método percorrerá todos os itens do array
preços e para cada iteração estamos somando o valor ao acumulador.

Ou seja, o primeiro valor do array é 3.50. Esse valor será somado com 0 na
primeira iteração, transformando o valor do acumulador em 3.50. Na
segunda iteração, o segundo valor será somado com 3.50 e o acumulador
passará a ser 8.50 ( 3.50 + 5 ) e assim até o último item.
Vamos colocar esse método dentro de uma variável e imprimi-la no console
para visualizarmos o resultado dessas iterações.

64
Agora vamos ao console.

Exatamente a soma de todos os itens daquele array.


Aqui usamos esse método com um array de números, mas poderia ser de
objetos ou strings também. Tente praticar você mesmo com outros
exemplos.

O próximo método que veremos é o find( ). Basicamente esse método irá


retornar o primeiro valor TRUE encontrado durante as iterações. Lembre-se
que estudamos quais valores são considerados TRUE e quais são
considerados FALSE. Uma string vazia é considerada FALSE por exemplo.
Mais uma vez vamos atribuir o método a uma variável e imprimi-la no
console.

65
Agora, veremos no console:

Logo na primeira iteração já encontramos um valor TRUE e por isso ele foi
retornado, mas se tivemos valores FALSE no início, ele retornaria apenas o
primeiro TRUE encontrado.

Se alterarmos dessa forma.

Veja que ele ignorou os primeiros itens pois são strings vazias, ou seja,
valores FALSE e retornou o primeiro valor TRUE que é “macarrão”.

O próximo é o método findIndex( ). É quase igual ao find( ) só que com a


diferença que ao invés de retornar o valor, ele retorna o index. Usando o
mesmo exemplo:

66
A primeira posição TRUE encontrada foi a posição 3, exatamente. Lembre-
se que o index começa da posição 0.

O próximo método é o some( ). Praticamente esse método retorna um


boolean. Caso exista pelo menos um valor TRUE no array ele retornará
TRUE. Caso não exista nenhum valor no array, ele retornarará FALSE.

Também temos o método every( ). Ele funciona ao contrário do some. Ele


precisa que todos os itens do array sejam TRUE para que ele retorne um

67
TRUE. Caso haja um único item no array que seja FALSE ele retornará FALSE
também.

Por último temos o método filter( ). Esse método retorna um novo array
contendo apenas os itens cujo valor é igual ao passado no método.

Nesse caso, um novo array será criado contendo todos os itens que tiverem
o valor idêntico à “arroz”.

Por hora é o que precisamos conhecer sobre arrays e seus iteradores.

FUNÇÕES
Falaremos agora sobre métodos e propriedades das funções. Não veremos
todos, apenas os principais. Mesmo os principais, não usaremos tanto no
dia a dia mas é importante ter o conhecimento.
Começaremos criando um exemplo contendo uma função.

68
Um função bem simples que espera um parâmetro “nome” e aproveita esse
valor recebido imprimindo ele no console.
Começando pela propriedade length. Essa propriedade retorna a
quantidade de parâmetros que uma função tem.

Como essa função que criamos de exemplo possui apenas um parâmetro, o


retorno desssa propriedade seria 1 também.
Também há a propriedade name. Que retorna o nome da função. Logo:

Não segredo nenhum aqui.

Agora falando de métodos, temos o método call( ). Esse método executa a


função, podendo passar um novo valor para “this”. Ele permite que você
chame uma função em um determinado contexto, especificando
explicitamente o objeto que será usado como this dentro da função. A
principal utilidade do método call() é permitir que você reutilize uma função
em diferentes objetos, definindo o contexto this apropriado para cada
objeto. Isso pode ser útil, por exemplo, quando você tem uma função
genérica que opera em propriedades de um objeto e deseja usar essa
função em diferentes objetos. Veja a sintaxe.

69
O próximo método é o apply( ). Funciona bem parecido com o call( ). No
entanto, os argumentos para a função são passados dentro de um array.

A principal utilidade do método apply() é permitir que você chame uma


função e passe um array de argumentos para essa função. Isso é útil quando
você possui uma função que espera receber argumentos como um array,
em vez de argumentos individuais.

Por último, veremos o método bind( ). Também é parecido com o call( ),


com a diferença que ele não executa a função, mas retorna ela. Esse método
é capaz de armazenar o retorno de uma função onde passamos novos
valores para this em uma variável.

70
Isso é o que precisamos saber sobre métodos e propriedades do construtor
de funções. Não é tão comum utilizar isso no dia a dia, mas é importante
conhecer.

OBJETOS
Veremos agora alguns dos principais métodos e propriedades do construtor
de objetos. Geralmente acessamos esses métodos e propriedades
diretamente pelo nome do construtor. Até agora, já lidamos um pouco com
objetos usando dot notation.

Quando temos um objeto, ao chama-lo pelo nome e usar dot notation,


acessamos aos métodos e propriedades daquele objeto em si. Mas como
acessar os métodos e propriedades herdadas do construtor? Chamando
pelo nome do construtor: Object.
Vamos começar estudando o método assign( ).

Serve basicamente para colocar os métodos e propriedades de um objeto


em um outro objeto. Vamos para a prática.

71
Aqui temos dois objetos: dados e endereco. Abaixo temos o método assign
sendo executado a partir do construtor Object. Esse método deve receber
dois parâmetros. O primeiro parâmetro é o objeto alvo, ou seja, o objeto
que irá receber os dados, o objeto que deseja-se acrescentar outro objeto
à ele. O segundo parâmetro é qual objeto deverá ser acrescentado ao objeto
alvo. Nesse exemplo, o objeto alvo é dados e o objeto que vamos colocar
dentro de dados é o objeto endereco. Vamos ver o resultado disso no
console?

Adicione um console.log( ) em dados.

Veja no console do navegador e constate que agora o objeto dados também


possui as propriedades do objeto endereco.

72
Existe uma outra forma de se chegar nesse mesmo resultado. É possível usar
o Spread, que já aprendemos anteriormente.

Essa é uma sintaxe muito simples, basta adicionar três pontos e o nome do
objeto que automaticamente as propriedades e métodos desse objetos
serão colocadas ali. Veja no console do seu navegador e constate que o
resultado é o mesmo.
Agora vamos ver o método Keys( ). Keys significa chaves. As chaves de um
objeto são os nomes atribuídos que recebem valores.

Podemos dizer que name e idade são chaves do objeto dados. Usando o
método Keys( ), como você deve imaginar, visualizaremos todas as chaves
presentes dentro de um determinado objeto.

73
Estamos chamando o método Keys( ) através do construtor Object dentro
do console.log( ) e estamos passando como argumento o objeto endereco.
Vejamos o que é retornado no console:

Mas porque aparecem as chaves do objeto dados sendo que passamos o


objeto endereco dentro do método? Lembre-se, estamos usando o Spread
para espalhar o objeto dados dentro de endereco. Logo, as chaves do objeto
dados passam a estar presentes dentro de endereco, por isso aparecem no
console ao executarmos o método Keys( ).
Também temos o método values( ), que como o nome já diz, ao invés de
retornar as chaves contidas dentro do objeto, retorna os valores das chaves.
Veja:

74
No console:

Esses não são os únicos métodos e propriedades do construtor Object. Mas


esses são os principais. O importante é compreender que, diferentemente
do construtor de strings por exemplo, acessamos os métodos e
propriedades através do próprio construtor de objetos e não diretamente
através do nome do objeto. Por enquanto é isso que precisamos saber.

NUMBER
Dando continuidade, estudaremos agora sobre os principais métodos e
propriedades do construtor de número, o Number. Antes de tudo, vamos
criar algumas variáveis que serão uteis nos nossos exemplos.

O primeiro método é o parseFloat( ). Esse retorna um número a partir de


uma string.

75
Note que estamos acessando o método através do nome do construtor
(Number.parseFloat). O valor da variável que está sendo passada é do tipo
string, mas após executar o método, tal valor é transformado em number,
permitindo assim operações aritméticas. Para entendermos melhor vamos
tentar fazer uma soma, primeiro do jeito errado, depois do jeito certo.

Essa seria a forma errada. Veja o que sai no console:

O resultado saiu 2010 e não 30 como o esperado, pois o numero 20 contido


na variável string está justamente em formato de string e quando tentamos
somar um dado que é string com um dado que é number, JavaScript
entende que se trata de uma concatenação (união de dois valores) e não de
uma operação aritmética de soma. Agora vamos ao jeito certo.

Esse é o jeito certo. Primeiro estamos convertendo o valor da variável string


em numero, depois estamos somando com o valor de numero.

76
Veja o resultado no console:

Agora sim! Como são dois dados do tipo number, JavaScript entende que é
uma operação aritmética e soma os valores. Poderiamos também subtrair,
multiplicar, dividir ou fazer qualquer operação aritmética aqui.

O próximo método é o parseInt( ), que funciona quase igual ao parseFloat,


porém com a diferença que nesse método, a string é convertida para um
número interiro. Diferentemente do parseFloat( ), que leva em
consideração as casas decimais, o parseInt( ) arredonda para um número
inteiro, ignorando qualquer valor decimal. Veja:

Suponhamos que a string que queremos converter possua uma casa


decimal. Ao usar o método parseInt( ) teremos no console:

77
O próximo método é o toFixed( ). Esse método é bastante usado quando
queremos arredondar algum número. Por exemplo:

Esse caso retornará 11. A regra é bem simples. Se a casa decimal for menor
que 50 arredondará para menos, se for igual ou maior que 50 arredondará
para mais.

Esse caso retornará 10. Faça os testes você mesmo.


O método toFixed( ) também pode ser usado para determinar a quantidade
de casas decimais que um número deve ter. Basta passar o número de casas
decimais pretendido como argumento do parâmetro:

78
O retorno:

Duas casas decimais.

Agora vamos para o método toString( ), que como o nome mesmo já diz,
converte um dado number para string, exatamente ao contrário do método
parseInt( ) ou parseFloat( ).

O retorno será uma string ‘10’.

O próximo método é o abs( ), acessado através do construtor Math.


Primeiramente, Math é um construtor nativo que contém vários métodos
de expressões matemáticas. Veremos quais métodos são esses e o que eles
fazem.
Começando pelo método abs( ) que retorna um número absoluto. O que é
um número absoluto?
É um valor que indefere se é negativo ou positivo. Então:

79
Em ambos os casos, o retorno é número absoluto, independente se eu
passo positivo ou negativo.

O próximo método é o ceil( ), que arredonda qualquer número para cima


independente da casa decimal.

Apesar no valor presente na variável ser 10.4 o retorno será 11, mesmo a
decimal sendo menor que 50.
Já o método floor( ), ele sempre arredondará para baixo.

O retorno nesse caso será 10, mesmo a decimal sendo 90.

80
Agora o método round( ), funciona parecido com o toFixed( ), arredondando
para o número mais próximo.

Temos também o método random( ), que retorna um número aleatório


entre 0 e 1.

Mas se eu quiser um número aleatório entre 0 e 200 por exemplo? Nesse


caso basta adicionar esse valor multiplicando pelo método:

A cada vez que você atualizar a página terá um número aleatório entre 1 e
200. Você pode colocar qualquer número, 200 é só um exemplo. Você verá
que as vezes o número virá “quebrado”, mas é só combinar com o método
parseInt( ) para ter sempre números inteiros.

Verifique os números retornados no console conforme você atualiza a


página.

81
O próximo método é o max( ), que retorna oo maior entre os números
listados.

E por fim o método min( ), que retorna o menor entre os números listados.

DATE
Date é o construtor de datas nativo do JavaScript. Vamos aprender sobre
seus métodos e propriedades na prática.
Primeiro declaramos uma variável e atribuímos como valor a execução do
método.

Agora vamos acessar outros métodos a partir dessa variável:

82
Duas importantes observações:
O valor retornado pelo método getMonth( ) em JavaScript é baseado em
zero-based indexing, o que significa que os meses são representados por
números de 0 a 11, em vez de 1 a 12. Portanto, 0 equivale a Janeiro, 1 a
Fevereiro e assim por diante.

O método getDay( ) retorna o dia da semana em formato numérico, onde


domingo é representado por 0, segunda-feira por 1, terça-feira por 2 e assim
por diante, até sábado, que é representado por 6.

Agora vá até o console, atualize a página no navegador e verifique os


resultados.

ESCOPOS
Aqui iremos estudar um pouco sobre escopos. A principio é um tópico
simples mas que precisa ser entendido e estudado. Podemos começar a
entender sobre escopos dentro de JavaScript tomando como exemplo
variáveis. O escopo equivale a um determinado local do código onde uma
variável pode ou não ser acessada. Por exemplo, uma função. Se eu criar
uma variável dentro de uma função, logo os limites daquela função serão o
escopo daquela variável, ou seja, não será possível acessar aquela variável
de fora da função, apenas dentro dela. Já uma variável criada fora, pode ser
usada dentro de uma ou mais funções, pois seu escopo já seria mais
abrangente nesse caso. Vamos ver na prática.

83
Nesse exemplo, temos uma variável criada fora de uma função. Então,
podemos tranquilamente usa-la dentro da função. Veja no console:

O valor da variável foi impresso corretamente.

Uma variável criada dentro da função, não poderá ser acessada fora dela
caso seja criada com const ou let. Aqui temos um exemplo prático da
diferença entre var, let e const, é uma diferença de escopo. Variáveis criadas
com let e const dentro de uma função manterão o seu escopo, portanto se
eu tiver uma outra variável com o mesmo nome fora da função não haverá
nenhum conflito, isso é uma boa prática. Por isso, a forma var de se declarar
variáveis tem ficado obsoleta, pois seu escopo pode “vazar” de dentro de
uma função, gerando conflitos com outras variáveis fora de escopo.

Para declarar variáveis use sempre let e const.

Temos escopos de blocos também. Por exemplo, dentro das condicionais


como if e como os laços de repetição como for. Qualquer variável criada
dentro de um bloco ou função terá o seu escopo de alcance apenas dentro
daquele bloco ou função.

84
Veja que aqui, criamos uma variável dentro da função e criamos outra com
o mesmo nome fora. Observe que os valores atribuídos são diferentes. Isso
jamais seria possível dentro do mesmo escopo, pois uma variável const não
pode ter seu valor redeclarado. Agora olhe no console.

O valor acessado é o valor que está fora da função. Então toda vez que eu
criar uma variável dentro de uma função ou bloco, seu valor só poderá ser
acessado dentro daquele escopo.

SÍNCRONO, ASSÍNCRONO E PROMISES


Dando continuidade, aprenderemos nessa parte sobre processamentos
síncronos, assíncronos e promises. Primeira coisa que precisamos entender
é a diferença de um processamento síncrono e processamento assíncrono.
• SÍNCRONO: No processamento síncrono, as operações são
executadas em ordem sequencial, uma após a outra. Isso significa
que cada operação deve ser concluída antes que a próxima comece.
Se uma operação levar muito tempo para ser realizada, ela bloqueará
a execução do restante do código. Durante esse bloqueio, a interface

85
do usuário pode ficar congelada, tornando a experiência do usuário
negativa.

• ASSÍNCRONO: No processamento assíncrono, as operações são


executadas em segundo plano e não bloqueiam o restante do código.
Isso permite que outras tarefas continuem sendo executadas
enquanto a operação assíncrona está sendo processada. Quando a
operação é concluída, uma função de retorno (callback) ou uma
promessa é acionada, permitindo que o código reaja aos resultados.

E o que são promises?


Uma Promise (Promessa) é um objeto JavaScript que representa a
conclusão (ou falha) eventual de uma operação assíncrona, e pode produzir
um valor único quando essa operação é bem-sucedida ou uma razão para a
falha quando ela não é. Em essência, é uma forma de lidar com operações
assíncronas de maneira mais elegante e estruturada, tornando o código
mais legível e fácil de gerenciar.
Uma promise tem duas possibilidades de retorno. Ela pode ser resolvida
(resolve) ou rejeitada (reject). Obviamente, resolvida é quando aquela
operação é bem sucedida, rejeitada é quando dá algum erro.

Vamos pro exemplo prático usando o construtor de promises.

Observe que declaramos uma variável const e atribuímos como valor o


método construtor de promises utilizando a palavra reservada new. Note
também que estamos executando com os parênteses, pois trata-se de um
método.
Agora, podemos passar dentro do método Promise, uma função call-back,
que por padrão, recebe dois argumentos, o resolve e o reject.

86
Agora, dentro de chaves, podemos ter uma condição sendo processada.
Apenas para efeito de exemplo, vamos criar uma variável cujo valor será um
boolean.

Inicialmente vamos deixar o valor false. Em seguida, podemos adicionar


uma lógica que verifique essa condição, podemos usar um if por exemplo.

Um estrutura de condicional simples. Se ( if ) o valor de condição for true,


chamamos o resolve( ), caso contrário ( else ), chamamos o reject( ). Claro,
isso é apenas um exemplo, na pratica faremos isso de uma forma um tanto
diferente, usando o then e o catch. O then representa o que fazer caso a
promise seja resolvida e o catch representa o que fazer caso a promise seja
rejeitada. Podemos usar também funções call-back para ambos os casos.

A seguir, um exemplo de código.

87
Primeiro declaramos o then e o catch dessa forma.

Depois passamos as funções call-back, tanto dentro do then como dentro


do catch. Essas funções recebem argumentos equivalentes. O call-back
dentro de then receberá o resultado da promise resolvida, pode ser algum
dado como um array, um objeto, enfim. Já o call-back dentro de catch
recebe geralmente um erro. Então, de posse desses call-backs podemos
determinar o que fazer com eles. Nesse exemplo estamos determinando
que caso a promisse seja resolvida iremos exibir o resultado em um alert( ),
caso seja rejeitada, exibiremos o erro no console. Novamente, esse é um
exemplo simples, no dia-a-dia iremos tratar esse resultado e esse erro de
uma forma mais adequada e podemos ter mais funcionalidades dentro do
bloco do que um simples alert( ) ou console.log( ). Mas aqui já dá pra termos
uma noção de como as coisas acontecem.
Vamos visualizar tudo isso no console do navegador? Antes disso, faremos
apenas uma alteração no nosso código de exemplo:

88
Precisamos passar dentro do resolve e do reject o que queremos exibir.
O código completo ficou assim:

Agora salve no seu VS Code e abra o console no navegador:

Nossa promise foi rejeitada e o call-back dentro de catch foi acionado. Por
que isso aconteceu? Porque a nossa condição resultou em false. Mas se
mudarmos para true:

89
Veja no navegador:

Nossa promise foi resolvida e o call-back dentro de then foi acionado,


disparando o alert com a mensagem “Resolvido”.
Vamos usar muito esses conceitos na prática. Então é muito importante que
você entenda como as coisas estão acontecendo, o que é um
processamento síncrono, assíncrono, o que é uma promisse, como lidar com
o then, com o catch, enfim. Nenhum desses conceitos pode ser ignorado. A
seguir daremos continuidade nos nossos estudos em JavaScript.

FETCH E JSON
Fetch é um método nativo do JavaScript que nos permite fazer requisições
HTTP. Tal requisição, podemos dizer que é uma promise, que pode ser
resolvida ou rejeitada como aprendemos anteriormente. Logo, podemos
usar o then( ) e o catch( ) para interagir com os retornos dessa requisição.
Vamos relembrar um pouco o que é HTTP.
HTTP (Hypertext Transfer Protocol) é o protocolo padrão usado para
transferir informações na World Wide Web (Internet). Ele permite que os
navegadores web solicitem páginas e recursos (como imagens, vídeos, etc.)
de servidores web e recebam as respostas. O HTTP é baseado no modelo
cliente-servidor, onde o cliente (navegador) faz solicitações para o servidor
e o servidor envia as respostas contendo os dados solicitados. É
fundamental para a comunicação entre navegadores e servidores na
internet e permite que as páginas da web sejam carregadas em seu
dispositivo.

90
Os cinco principais métodos de requisição HTTP, também conhecidos como
verbos HTTP, são:
1. GET: É usado para solicitar dados de um recurso específico no
servidor. O servidor responderá enviando os dados solicitados na
resposta.
2. POST: É usado para enviar dados para o servidor, geralmente para
criar um novo recurso ou realizar uma ação que pode alterar o estado
do servidor.
3. PUT: É usado para enviar dados para o servidor com a finalidade de
atualizar um recurso específico. Ele substitui completamente o
recurso existente pelos dados enviados.
4. DELETE: É usado para solicitar a remoção de um recurso específico do
servidor.
5. PATCH: É usado para enviar dados para o servidor com a finalidade de
atualizar parcialmente um recurso. Ao contrário do método PUT, que
substitui o recurso inteiro, o PATCH é usado para fazer alterações
específicas em partes do recurso.
Esses métodos de requisição permitem que os clientes interajam com os
servidores e realizem diversas operações na web, como obter informações,
enviar dados, criar, atualizar ou remover recursos.

Na prática, as requisições são feitas através do client, ou cliente. Client


representa o front-end, onde o usuário interage. Quando acessamos um site
estamos fazendo uma requisição HTTP através do navegador que está em
nosso computador. A requisição é feita para o servidor, que por sua vez
processa essa requisição e devolve uma resposta para o client. Logo, quando

91
acessamos um site, uma requisição HTTP é feita para um endereço de
servidor especifico (URL) e o servidor responde com a página HTML que esta
guardada naquele endereço. De forma me enxuta, é isso que acontece.

Em JavaScript vamos usar o fetch para fazer requisições para o nosso back-
end. Ainda não estamos sobre back-end, mas nos módulos seguintes vamos
estudar. Mas só para entender, vamos usar o fetch para fazer uma requisição
para o nosso back-end que por sua vez retornará uma resposta ao nosso
front-end. Essa resposta pode ser algum dado ou feedback em relação
aquela requisição, nesse caso trataríamos essa resposta dentro do then( )
como uma promise resolvida, ou pode ser um erro, em caso da requisição
não ser bem-sucedida por algum motivo. Se for um erro, será uma promise
rejeitada, portanto, tratada dentro do catch( ).

No momento da requisição precisamos informar qual o objetivo da mesma,


ou seja, se o objetivo é buscar algum dados, atualizar, deletar, enfim. Para
tanto, faremos o uso dos verbos HTTP mencionados anteriormente. Através
desses 5 principais verbos conseguimos criar as funcionalidades que
compõem o chamado CRUD, abreviação de CREATE, READ, UPDATE E
DELETE, que são as 4 operações básicas de um back-end.

E como é estabelecida essa comunicação entre front-end e back-end?


Através dos endpoints. O que são?
Nada mais, nada menos do que URL´s. Um endpoint é uma URL.
Determinar os devidos endpoints para cada funcionalidade de uma
aplicação é responsabilidade do back-end. Por exemplo, é o desenvolvedor
do back-end que vai determinar qual é o endpoint para criar um usuário,
qual o endpoint para atualizar dados de um usuário, qual endpoint para
deletar, etc. Também é função do back-end determinar quais dados
precisam ser enviamos nessa requisição para que a operação possa ser
concluída.

92
Também precisamos entender quais os tipos de parâmetros possíveis
dentro de uma requisição HTTP.
Dentro de uma requisição HTTP, existem quatro tipos principais de
parâmetros que podem ser usados para enviar informações entre o cliente
e o servidor:
1. Parâmetros de consulta (Query Parameters):
• O que são: São parâmetros incluídos na URL após o ponto de
interrogação (?).
• Como funcionam: São usados para enviar dados na forma
chave-valor, separados por "&". Exemplo:
www.exemplo.com/recurso?chave1=valor1&chave2=valor2.
• Uso comum: Fornecer critérios de busca, filtrar resultados ou
passar informações opcionais para uma solicitação GET.
2. Parâmetros de caminho (Path Parameters):
• O que são: São segmentos variáveis na própria URL,
geralmente precedidos por "/".
• Como funcionam: Permitem especificar valores específicos
para determinados recursos na URL. Exemplo:
www.exemplo.com/recurso/valor.
• Uso comum: Identificar recursos únicos em solicitações GET,
PUT, PATCH e DELETE.
3. Parâmetros de cabeçalho (Header Parameters):
• O que são: São informações adicionais incluídas no cabeçalho
da requisição HTTP.
• Como funcionam: São definidos como pares chave-valor nas
configurações de cabeçalho da requisição.
• Uso comum: Enviar detalhes sobre a requisição, como
autenticação, tipo de conteúdo aceito, idioma preferido, entre
outros.

93
4. Parâmetros de corpo (Body Parameters):
• O que são: São dados enviados no corpo da requisição,
geralmente usados em solicitações POST, PUT e PATCH.
• Como funcionam: Os dados são enviados em formatos como
JSON ou XML no corpo da requisição.
• Uso comum: Enviar informações mais complexas, como dados
de formulários, objetos ou atualizações para o servidor.
Esses parâmetros permitem que o cliente envie informações relevantes
para o servidor, permitindo que a aplicação web funcione de forma
dinâmica e interativa, respondendo adequadamente às solicitações feitas
pelos usuários. Cada tipo de parâmetro tem um papel específico em
diferentes tipos de solicitação e é essencial para a comunicação entre o
cliente e o servidor na web.

Para entendermos tudo isso na prática, existe um endpoint publico onde


podemos fazer requisições a fim de obter dados sobre crypto moedas.
Endpoint: https://api.coingecko.com/api/v3/exchange_rates

Agora, vamos inserir as devidas funções call-back para cada possível


resposta(resolve, reject).

94
Aqui, como já vimos anteriormente, as funções call-back recebem os
argumentos respectivos das suas respostas. Poderíamos colocar qualquer
nome, mas por padrão, adotamos data e error, para ficar mais adequado.
Em ambos os casos, estamos exibindo no console.
Mas só isso ainda não é o suficiente para funcionar. Como estamos fazendo
uma requisição de um cliente externo, ou seja, nosso computador, tal
requisição não será autorizada, por conta do CORS.
O CORS (Cross-Origin Resource Sharing) é uma política de segurança
implementada pelos navegadores web. Ela controla o acesso a recursos em
um servidor web a partir de origens (domínios) diferentes. Quando um
cliente (navegador) faz uma solicitação HTTP para um recurso em outro
domínio, o CORS verifica se essa origem está autorizada a acessar os
recursos do servidor. Se não estiver, a solicitação é bloqueada pelo
navegador. O CORS é importante para proteger os usuários contra possíveis
ataques maliciosos e garantir a segurança das informações na web.
Como resolver isso para que a nossa requisição funcione?

Basta adicionar esse objeto com o mode: ‘cors’ e já irá funcionar. Agora,
como podemos visualizar no console?

No console do navegador, vá até a aba network ou rede.

95
Clique em Exchange_rates e depois em preview ou visualizar.

96
Você verá que ali dentro tem o array contendo os dados das crypto moedas.

Essa foi a nossa primeira requisição HTTP.

Por padrão, as requisições feitas serão do tipo GET. Portanto, se eu não


mencionar o tipo da requisição ela será do tipo GET. Como estamos usando
esse endpoint justamente para colher dados, então naturalmente é uma
requisição do tipo GET mesmo, então por isso fizemos a requisição
diretamente sem mencionar o tipo. Mas caso nós quiséssemos enviar dados
ao invés de recebe-los, teríamos que fazer uma requisição do tipo POST.
Como ficaria na prática?

Informamos por meio da propriedade method o tipo, ou se preferir, método


da requisição.

97
Esse endpoint que estamos usando no exemplo não espera receber
requisições do tipo POST, então não funcionaria, é apenas para exemplificar
como mencionamos o método no momento da requisição.

E quais seriam as formas de enviar dados em requisições HTTP? Lembra que


existem 4 tipos de parâmetros? Vamos ver agora sobre cada um deles.

Body params
É a forma mais comum de enviar dados. Body significa corpo, ou seja, os
dados são enviados no corpo da requisição. Então, dentro do mesmo objeto
onde passamos o mode e o method, também passaremos o body.

Calma, apenas foi adicionado o body dentro do objeto. Apenas colocamos


cada propriedade em uma linha para facilitar a visualização. Observe que
body também é um objeto, portanto, podemos passar propriedades e
valores.

98
Dessa forma podemos passar parâmetros no corpo (body) da requisição.

Header params
Por hora não precisamos nos preocupar muito com ele, mas basicamente
aqui iremos passar informações adicionais a respeito daquela requisição,
como por exemplo o tipo/formato de dados que está sendo enviado (JSON
por exemplo), podemos passar um token de autenticação que seria uma
espécie de credencial que autoriza aquele usuário de fazer aquela
requisição ou não, etc. Mais pra frente veremos na prática a usabilidade
desses parâmetros.

Route params
É uma forma diferente de enviar dados. Dessa vez, os dados não são
passados dentro do objeto que estamos montando, mas sim, no próprio
endpoint.

Imagine que eu queira passar o ID de um usuário, a fim de realizar alguma


operação no banco de dados como excluir o usuário ou alterar dados do
mesmo. Esse ID não precisa ser passado no corpo, ele pode ser passado no

99
próprio endpoint. Os parâmetros de rota são separados por / . Por isso, no
exemplo colocamos /numerodoID. Claro, o endpoint precisa estar
configurado para receber esse dado através do Route param, o que não é o
caso desse enpoint de exemplo. Mas só para entender...assim estaria
configurado no back-end para receber esse parâmetro:

Dessa forma, o servidor espera que depois do parâmetro Exchange_rates


venha do front-end um dado que corresponda a um ID. Lembrando que o
nome que é colocado após os : é apenas referencia, poderia ser :userID por
exemplo. Funciona mais ou menos como os parâmetros que colocamos em
uma função. O que será levado em consideração não é o nome, mas sim a
ordem das informações.
Query params
É muito parecido com Route params, com a diferença que temos que passar
os dados ao final do endpoint. Então, suponhamos que o nosso endpoint
termine aqui:

Passariamos os query params ao final desse endpoint. Ao invés de usar


barra, usamos “?”, dessa forma:

Geralmente o valor que colocamos na query tem um teor de busca.


Normalmente é quando temos uma espécie de pesquisa a ser feita baseada
naquele valor, sendo que dependendo do valor colocado, a resposta pode
ser uma ou outra. Os Route params são mais voltados para editar
informações no servidor e os query params tem mais efeito de consulta,
filtro, etc. A sintaxe é essa do exemplo, colocamos “?” e passamos qual seria

100
a propriedade e o valor a ser consultado, por exemplo: Todos os usuários
com o name=Paulo.

Como podemos saber se uma requisição deu certo ou não? Através dos
status de resposta HTTP. Vamos relembrar?
Podemos dividir os status de resposta HTTP em quatro tipo:

1. Sucesso – Quando a requisição é bem sucedida.


2. Redirecionamento – Quando uma página é inexistente é o usuário é
redirecionado para outra página.
3. Erro no client – Quando algo está errado no front-end.
4. Erro no servidor – Quando algo está errado no back-end.

Vamos fazer novamente a requisição para o endpoint correto para olharmos


o status:

No console do navegador:

101
Recebemos status 200, significa que nossa requisição foi bem sucedida!
Então 200 é o único status de requisição bem sucedida? Não.
O intervalo entre 200 e 299 equivale a requisições bem sucedidadas. Não
vamos explicar aqui uma a uma pois seria impossível mas você pode
pesquisar sobre nessa documentação:
https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Status/200

Nesse link, do lado esquerdo você pode ir navegando entre os status e ver
um por um caso queira.

O intervalo entre 300 e 399 equivale a redirecionamento.


O intervalo entre 400 e 499 equivale a erro no client.
O intervalo entre 500 e 599 equivale a erro no servidor.

Realmente é muita informação, mas se precisar, revise a aula quantas vezes


for necessário.

Qual o formato dos dados que são enviados / recebidos?

Bom, podemos enviar e receber dados de qualquer formato, inclusive


documentos HTML, mas o mais comum é recebermos no formato JSON.
JSON é a sigla que abrevia: Javascript Object Notation.
É bom gravar essa nomenclatura pois ao longo da caminhada como
desenvolvedor vamos interagir muito com esse formato de dado.
Quando nos deparamos com um dado nesse formato, de cara vamos notar
muita semelhança com os objetos que já estudamos em Javascript. Uma das
principais diferenças é que as chaves desse objeto são no formato de string.
JSON também é normalmente encontrado como extensão de arquivos
(arquivo.json). Geralmente, tais arquivos, são arquivos de configuração.

102
No VS Code, você pode criar um arquivo com a extensão .json e escrever no
formato JSON, dessa forma.
Note que os dados são envolvidos por chaves { } e cada propriedade é no
formato de string. Já os valores podem ser strings, number, objects, arrays,
etc.

Também é possível ter vários objetos dentro de um mesmo JSON. Por


exemplo:

Nesse caso, os dados são envolvidos por colchetes. Outra coisa muito
importante é usar sempre aspas duplas.

103
Existem alguns métodos nativos em Javascript relacionados a JSON.
Temos o JSON.parse( ) que transforma uma string que está em um formato
JSON em um objeto Javascript.

Note que aspam simples definem a string e aspas duplas definem o formato
JSON. Podemos receber dados dessa forma e precisar convertê-los para
objeto JSON. Então usaremos o método parse para tanto.

Vejamos no console:

Temos um objeto.

Agora o método stringfy( ) fará o inverso. Ele converterá um objeto


Javascript em uma string de formato JSON.

104
É necessário revisar essas aulas mais de uma vez pelo volume de
informação. Não é tão fácil assim, mas com dedicação é possível.
Para finalizar essa parte de requisição para API com fetch( ), vou deixar um
site contendo várias API publicas e gratuitas para serem usadas para teste,
assim como essa API de dados de criptomoedas que usamos no exemplo.

https://mixedanalytics.com/blog/list-actually-free-open-no-auth-needed-
apis/

Contém uma lista grande de endpoints que podem ser usados para praticar.
Então, se esforce para pegar o conteúdo aprendido e por em prática para
fixar ainda mais os conhecimentos. Vale a pena conferir essas API´s publicas.

ASYNC E AWAIT
Vamos começar a aprender agora sobre async e await. O "async/await" é
uma construção fundamental em JavaScript para lidar com operações
assíncronas de maneira mais concisa e legível. Ao marcar uma função com
a palavra-chave "async", ela retorna automaticamente uma Promise e pode
conter pontos de espera ("await") dentro do seu corpo, permitindo que o
código aguarde a conclusão de chamadas assíncronas sem bloquear a
thread principal. Isso simplifica a escrita de código que lida com tarefas
como requisições de rede ou acesso a bancos de dados, tornando-o mais
semelhante à programação síncrona, porém mantendo a natureza
assíncrona e não bloqueante da linguagem.
Anteriormente, ao estudar sobre requisições HTTP, usamos o método fetch
para realizar nossas primeiras requisições. Então, usamos then e catch para
lidar com essa promisse. Agora, faremos praticamente o mesmo, só que
usando uma escrita mais limpa e performática.

105
Estamos usando aqui o seguinte endpoint:
'https://api.coingecko.com/api/v3/exchange_rates?id=3124234234&name
=P'
Perceba que agora estamos inserindo um async na declaração da função.
Fazemos isso para indicar que dentro da função teremos pontos de espera
(await).

Não podemos usar o await sem async.


Outra mudança é que o invés de usarmos o then( ), estamos armazenando
o retorno da promisse em uma variável chamada data. É como se
estivéssemos dizendo que a função deve aguardar o retorno dessa
requisição antes de executar a próxima tarefa.

106
Vamos colocar como próxima tarefa após a requisição terminar, exibir o
resultado no console. Lembre que precisamos executar a função para isso.
Abra o console no seu navegador e veja:

No console ainda não aparecem os dados das moedas, mas basta seguir o
passo a passo da aula anterior e ir na aba network ou rede.

Temos aqui os dados das cripto moedas.

107
Mas e se eu quiser usar de fato esses dados em um projeto?
Bem, nesse caso precisaremos converter a resposta para o formato JSON,
dessa forma:

Também usamos await na hora de converter para JSON, pois essa


operação também é uma promisse. Agora veja no console do seu
navegador:

Pronto. Agora você tem os dados no formato JSON diretamente na variável


data. Aqui estamos exibindo no console. Mas você poderia salvar em um
array por exemplo e usar o método map( ) ou forEach( ) para interagir com
esses dados, fazendo com que essas informações apareçam em tela. Nesse
módulo teremos um projeto prático onde vamos consumir uma API do
Star Wars usando async, await, fetch e forEach.

108
Existe uma outra coisa que precisamos aprender antes de prosseguir, estou
falando do try e do catch. Try significa tentar e catch significa pegar. É bem
parecido com then e catch mas com uma escrita mais moderna.

A vantagem de usar try e catch é poder dividir realmente o sucesso do erro.


É como se disséssemos: Tente isso (requisição), se der certo converta os
dados para JSON e exiba no console os dados convertidos, caso contrário,
se a requisição não der certo por algum motico pegue o erro e exiba no
console.

Da forma como está vai funcionar, mas experimente mudar alguma coisa no
endpoint, ou seja, provoque o erro e compare os resultados no console.

Isso que acabamos de aprender é amplamente usado no dia a dia de um


desenvolvedor. Então, não deixe de absorver os conceitos e praticar antes
de avançar.

DOM E WINDOW
Nessa aula, vamos estudar sobre DOM e o objeto global window,
principalmente e também o objeto document que está contido dentro de
window. Aqui vamos nos aprofundar no conceito árvore DOM e como
manipular elementos com JavaScript.

109
DOM é uma acrônimo para Document Object Model. Basicamente é uma
estrutura que representa os elementos HTML. Através do DOM
conseguimos criar, alterar e manipular elementos HTML como criar uma div,
inserir o nome de uma classe, obter o valor digitado pelo usuário em um
input, tudo isso com JavaScript.

Essa é uma imagem que representa a árvore DOM.


Perceba que a partir de window temos acesso à location, document e
history. Aqui vai um breve resumo sobre o conteúdo de cada um:
1. location: O objeto location faz parte do objeto global window e
representa a URL do documento atual. Ele permite que você acesse e
manipule informações sobre a URL, como o endereço completo,
partes específicas (como o hostname, pathname, etc.) e até mesmo
redirecionar para outras páginas. É comumente usado para obter
informações sobre a URL da página e para navegar para novas URLs.
2. document: O objeto document também é parte do objeto global
window e representa a estrutura HTML de uma página da web. Ele

110
fornece métodos e propriedades para acessar, modificar e interagir
com os elementos HTML presentes na página. Por meio do objeto
document, você pode selecionar elementos por meio de seletores
CSS, criar novos elementos, alterar conteúdo, estilos e muito mais.
3. history: O objeto history também é parte do objeto global window e
mantém um histórico de navegação do navegador. Ele permite que
você navegue entre as páginas visitadas anteriormente. O objeto
history oferece métodos para mover-se para a página anterior,
próxima ou para uma página específica no histórico. No entanto,
devido a razões de segurança, você não pode acessar as URLs reais
no histórico, apenas manipular a posição de navegação.

No nosso navegador podemos visualizar todos os outros métodos e


propriedades do objeto window. Abra a parte de ferramentas do
desenvolvedor usando CTRL + SHIFT + i e pesquise por window, após
isso tecle ENTER.

111
Você pode navegar e ir analisando cada um, porém é impossível
conhecer tudo. Vamos nos apegar em aprender sobre os principais e
mais usados, location, document e history, sendo que dentre eles o
mais usado é o document.

Algo é importante observar. Você deve ter notado que um dos métodos
dentro de window é o alert.

Então se executarmos window.alert( ), a página exibirá um alerta.

Mas nós já usamos o alert( ) antes e sem mencionar o window, porque


funciona da mesma forma? Como window é um objeto global, quando
executamos um método dele já é interpretado que aquele método vem
de window, então não precisamos menciona-lo diretamente.

Caso queira se aprofundar mais em métodos e propriedades dos


principais objetos de window, segue abaixo as respectivas
documentações. As páginas estão em inglês mas é perfeitamente
possível traduzi-las com seu navegador.

112
Documentação Window:
https://developer.mozilla.org/en-US/docs/Web/API/Window
Documentação Document:
https://developer.mozilla.org/en-US/docs/Web/API/Document
Documentação History:
https://developer.mozilla.org/en-US/docs/Web/API/History_API
Documentação Location:
https://developer.mozilla.org/en-US/docs/Web/API/Location

Dentre os métodos presentes em document, podemos destacar o


getElementById( ), que nos permite manipular um elemento HTML por
meio do seu id. Vamos aprender sobre isso na prática através do
projeto prático Star Wars Characters que faremos na sequencia e
também na aula 08 de aulas ao vivo, onde é desenvolvida uma
calculadora de IMC. Não deixe de assistir essas aulas e desenvolver os
dois projetos práticos.

COOKIES, LOCAL STORAGE E SESSION STORAGE


Nessa aula vamos aprender sobre os três tipos de armazenamento no
client. Primeiro, entenda que o client é basicamente o navegador que o
usuário utiliza. Vamos começar entendendo quais são e a diferença entre
cada um deles. Utilizando Javascript, temos três tipos de
armazenamento local no client.
Para tanto, vamos usar o seguinte site:
https://www.tutorialspoint.com/difference-between-local-storage-
session-storage-and-cookies-in-javascript#
O site está em inglês mas é possível traduzi-lo.

113
Resumindo:
Local storage é o mecanismo mais recente. Permite armazenar maiores
quantidades de dados, mas os dados não são excluídos quando o
navegador é fechado. O armazenamento local é útil para armazenar
dados que o usuário precisará acessar posteriormente, como dados
offline.
Session storage é semelhante aos cookies, mas os dados são
armazenados apenas para a sessão atual. Isso significa que os dados
serão excluídos quando o usuário fechar o navegador. O armazenamento
de sessão é útil para armazenar dados confidenciais, como credenciais
de login.
Cookies são o mecanismo mais antigo e conhecido. Eles são simples de
usar e bem suportados pelos navegadores. No entanto, eles são
limitados a 4 KB de dados e são frequentemente usados para armazenar
dados que não são confidenciais, como preferências do usuário.

O local storage é muito útil quando vamos fazer a autenticação de


usuário. Imagine que temos um site com sistema de login e queremos
que o usuário permaneça logado por um determinado período. Ainda
que ele feche a página, desligue o computador, etc; quando ele acessar
novamente o site estará logado. Usamos o local storage para armazenar
o token de autenticação que é consultado sempre que o usuário acessar
o site. Todo token de autenticação tem um prazo de expiração que é
determinado pelo desenvolvedor. Depois que o prazo expirar, o usuário
precisará fazer login novamente, então um novo token será armazenado
no local storage. Esse é apenas um exemplo de uso, mas pode ser usado
para outras coisas também.

Os cookies são mais conhecidos. Toda vez que acessamos um site somos
questionados quanto a permissão de cookies. Basicamente eles
armazenam preferencias do usuário que podem servir de base para
algoritmos estratégicos daquele site. Por exemplo: Se o usuário acessa
um site de vendas e começa a clicar em anúncios de eletrônicos, essa
informação pode ser armazenada nos cookies e da próxima vez que
aquele usuário acessar o mesmo site, aparecerão diversos anúncios de
114
eletrônicos. Outra coisa é o tema de cor. Boa parte dos sites possui tema
light e dark (claro e escuro). Se o usuário escolhe o tema dark, isso pode
ser armazenado nos cookies para que sempre que o usuário acessar
aquele site ele esteja no tema dark.

E como fazemos para salvar dados no local storage e depois acessá-los?


O processo é bem simples.

No nosso arquivo Javascript, chamamos localStorage seguido do método


setItem usando o dot notation. Esse método precisa de dois argumentos
que equivalem a chave e valor, bem parecido com um objeto, mas não
é. Chave e valor é necessário para termos um identificador daquele
dado. Tudo que é armazenado no local storage é no formato de string,
então primeiro passamos uma string que seria a chave identificadora e
em seguida passamos a string que seria o valor daquela chave. No nosso
exemplo estamos passando a chave “name” e o valor “Paulo”.
Feito isso, já conseguimos visualizar essa informação no navegador.
Atualize a página no navegador e abra as ferramentas do desenvolvedor
usando o atalho CTRL + SHIFT + i.

115
Clique nas setas de navegação das abas e depois clique em application
ou aplicação.

Procure por local storage e clique no endereço da página. Do lado direito


você poderá visualizar a chave o valor.

Também é possível excluir esses dados se quisermos.

Podemos usar o botão com ícone de proibido para limpar todos os dados
do local storage relacionados aquela página ou clicar com o botão direito
do mouse em cima do dado que aparecerão as opções de deletar ou até
mesmo editar.

116
E como fazemos para obter o dado que está salvo no local storage?
Bem simples também:

Basta usar o método getItem e passar a chave como argumento. Aqui


estamos armazenando o dado na variável userName e depois usando
para exibir um alert, veja no seu navegador:

Da mesma forma eu poderia usar esse dado em uma função, objeto ou


qualquer outra coisa. Se esse dado fosse um token de autenticação, eu
poderia usa-lo para fazer uma requisição para o back-end e obter dados
do usuário, autenticá-lo, enfim.

Com o session storage funciona da mesma maneira.

117
Existem outros métodos além de setItem e getItem.

Podemos usar o clear e o removeItem também.

Para salvar nos cookies é bem parecido:

A diferença é que cookie está dentro do objeto document e não dentro


de window. No caso de local storage e session storage podemos chama-
los diretamente pelo nome pois estão dentro do objeto global window,
mas como cookie está dentro de document precisamos chamar primeiro
document para depois chamar cookie.
Pode ser que você encontre algum problema para salvar um dado nos
cookies de forma local, mas é possível fazer isso usando qualquer outro
site e executando esse comendo nas ferramentas de desenvolvedor:
Use o site mencionado nessa aula para praticar:

118
Abrindo o console no navegador, execute o comando e tecle ENTER.
Depois vá na aba aplication, procure por cookies e clique na página:

Lá está.

Nessa aula aprendemos tudo que é necessário por hora em relação a


armazenamento no client. Mas caso queira se aprofundar mais no
assunto, o site citado no início fornecerá maiores informações.

119
JAVASCRIPT MODULES
Nossa última aula antes do projeto prático é sobre JavaScript Modules.
Esse conceito nada mais é do que dividir nosso código JavaScript em partes,
possibilitando usarmos trechos de códigos separados em nosso projeto. Isso
é útil para a organização do código. Imagine que temos um arquivo principal
e não queremos criar todos os códigos e funções dentro dele. Então
podemos criar outros arquivos contendo trechos específicos e exporta-los,
logo, temos um módulo sendo exportado. Uma vez que exportamos,
podemos importar e usar no arquivo principal.

Bom, script.js é o nosso arquivo principal. Vamos criar um outro arquivo


chamado module.js (ou o nome que quiser dar) onde vamos criar e exportar
um módulo. Mas antes de fazer isso, precisamos fazer uma alteração no
nosso arquivo index.html:

120
Adicione o atributo “type” a tag script e atribua o valor "module”. Feito isso,
vamos para o arquivo module.js.

Vamos criar uma função simples e exporta-la. Aqui é uma simples função
que exibe um alerta, mas poderia ser algo mais complexo, é apenas um
exemplo para fixar o conceito. Observe que usamos a palavra reservada
export antes da declaração da função.

Agora no nosso arquivo principal script.js, usamos a palavra reservada


import para importar o módulo antes exportado. Entre chaves, colocamos
o nome da função. Depois, usamos outra palavra reservada que é from, que
vai indicar o caminho do arquivo de onde estamos importando aquele
módulo.
Uma vez que o módulo foi importado corretamente, podemos usá-lo
normalmente, como se aquele código tivesse sido escrito no mesmo
arquivo. A vantagem disso é que se tivéssemos uma função extensa, isso
deixaria nosso arquivo principal bem mais limpo. É importante que o
desenvolvedor avalie se vale a pena ou não criar determinado trecho de
código em um arquivo separado ou não. Não faria sentido criar um arquivo

121
separado apenas para uma função simples, só fizemos isso para fim de
exemplo.
Também é possível exportar mais de um item se quisermos:

Podemos exportar uma variável ou outra função. Note que alteramos um


pouco a função fazendo com que ela espere um argumento.

Quando a origem é do mesmo arquivo, podemos importar dentro das


mesmas chaves apenas separando por vírgula. Agora chamamos a função
passando como argumento uma das propriedades do objeto colors que foi
importado.

No seu navegador deverá aparecer assim.


122
Quando começarmos a estudar ReactJS veremos a importância de saber
exportar e importar módulos.
Existem duas formas de exportar módulos. Uma nós já vimos acima. A outra
é utilizada apenas quando temos um único item sendo exportado.

Caso tenhamos um único item a ser exportado, podemos usar o export


default, que é o nome padrão para importação daquele módulo. Agora, se
tenho mais de um item para ser exportado no mesmo arquivo, então
devemos exportar individualmente como fizemos anteriormente.

Quando importamos um item que foi exportado como default, não


precisamos usar chaves.
Podemos ter vários arquivos exportando módulos distintos e importar
todos eles dentro do mesmo arquivo principal.

Esse módulo foi bastante extenso realmente, mas acredito que você pode
absorver o conteúdo passado. A seguir, teremos nosso projeto prático de
JavaScript onde construiremos do zero um site que console a API do Star
Wars e exibe informações dos personagens em tela. Nesse projeto
colocaremos em prática a maioria dos conceitos aprendidos nesse módulo
e mais algumas outras coisas. Até lá.

123

Você também pode gostar