Apostila PP - Módulo 04
Apostila PP - 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.
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.
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:
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:
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.
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
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.
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.
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?
13
Vamos visualizar essa variável no console adicionando um console.log( ) e
passando essa variável dentro. Dessa forma:
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:
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.
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?
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.
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:
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:
20
Podemos clicar também na setinha de prototype e ver que o método que
criamos está lá.
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.
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:
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:
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:
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?
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.
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.
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:
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:
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:
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:
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.
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:
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.
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:
40
No console:
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:
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 é:
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.
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:
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:
Teríamos:
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.
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:
49
Agora temos 6 itens no array. Se adicionarmos mais um console.log em
array, veremos o novo item presente.
50
A primeiro console está imprimindo o item que foi removido e o segundo
mostra o array atualizado.
No console:
51
No console:
Removido sucesso.
52
Isso certamente retornará FALSE.
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.
54
Usando new Array( )
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.
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.
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.
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:
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:
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:
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.
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.
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.
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.
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.
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”.
66
A primeira posição TRUE encontrada foi a posição 3, exatamente. Lembre-
se que o index começa da posição 0.
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”.
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.
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.
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.
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?
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:
74
No console:
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.
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.
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.
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.
78
O retorno:
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( ).
79
Em ambos os casos, o retorno é número absoluto, independente se eu
passo positivo ou negativo.
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.
80
Agora o método round( ), funciona parecido com o toFixed( ), arredondando
para o número mais próximo.
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.
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.
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.
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:
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.
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.
85
do usuário pode ficar congelada, tornando a experiência do usuário
negativa.
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.
87
Primeiro declaramos o then e o catch dessa forma.
88
Precisamos passar dentro do resolve e do reject o que queremos exibir.
O código completo ficou assim:
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:
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.
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( ).
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.
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?
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.
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.
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.
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.
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:
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:
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.
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.
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.
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).
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.
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:
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.
Da forma como está vai funcionar, mas experimente mudar alguma coisa no
endpoint, ou seja, provoque o erro e compare os resultados no console.
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.
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.
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.
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
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.
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.
115
Clique nas setas de navegação das abas e depois clique em application
ou aplicação.
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:
117
Existem outros métodos além de setItem e getItem.
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á.
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.
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.
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:
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