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

Javascript Subprogramação

O documento aborda a subprogramação em JavaScript, focando em funções, métodos de objeto e módulos. Ele explica como criar e invocar funções, passando parâmetros e lidando com múltiplos parâmetros para personalizar notificações. Exemplos práticos são fornecidos para demonstrar a implementação de funções em uma aplicação web, incluindo a manipulação do DOM.

Enviado por

ademarnetodev
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)
0 visualizações44 páginas

Javascript Subprogramação

O documento aborda a subprogramação em JavaScript, focando em funções, métodos de objeto e módulos. Ele explica como criar e invocar funções, passando parâmetros e lidando com múltiplos parâmetros para personalizar notificações. Exemplos práticos são fornecidos para demonstrar a implementação de funções em uma aplicação web, incluindo a manipulação do DOM.

Enviado por

ademarnetodev
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

Javascript

Aula 09

<Módulo 06/>
Subprogramação

Sumário

• Funções

• Introdução

• Invocação de função no Console (só para testar)

• Invocação de função no meio do código da aplicação

• Parâmetro

• Múltiplos parâmetros

• Cuidado ! Passagem por valor e por referência

• Cuidado ! Shadowing

• Valor de retorno

• Métodos de objeto

• Introdução

• Definindo funções como propriedades de um objeto

• Invocando os métodos

• Palavra-chave this dentro de um método

• Módulos

• Módulos

• Criando Módulos

• Componentes

• Controle de tempo
Funções
Introdução
Dentro de uma página web, há várias situações onde você poderia querer notificar o usuário sobre o
resultado de ações dele.
Por exemplo, quando ele adiciona uma tarefa numa lista de tarefas, uma notificação dizendo “tarefa
adicionada com sucesso”, ou “falha na criação da tarefa”.
A função alert() pode ser usada para isso, mas a janela de alerta é feia ! E não pode ser customizada
com CSS.
Seria legal se existisse alguma outra função que mostrasse um alerta mais bonito, mas não existe.
Se não existe, podemos criar essa função.
Por exemplo:

function showNotification() {
// Estrutura da notificação:
// <div><div>mensagem</div><div>❌</div></div>

// uma div escura posicionada no canto direito inferior da tela.


// O estilo está todo definido aqui por facilidade, mas
// poderia estar num arquivo CSS
const container = [Link]("div");
[Link] = "absolute";
[Link] = "24px";
[Link] = "24px";
[Link] = "300px";
[Link] = "32px";
[Link] = "8px 24px";
[Link] = "flex";
[Link] = "center";
[Link] = "space-between";
[Link] = "#202124";
[Link] = "white";
[Link] = "4px";
[Link] =
"0 1px 3px 0 rgba(60, 64, 67, 0.302), 0 4px 8px 3px rgba(60, 64, 67, 0.149)";

// div contendo uma mensagem


const messageDiv = [Link]("div");
[Link] = "Mensagem aqui";

// botão de fechar (é uma div)


const closeButton = [Link]("div");
[Link] = "❌";
[Link] = "pointer";

[Link](messageDiv);
[Link](closeButton);

// colocar o container no final do <body>


// (não realmente importa onde, porque
// a posição é "absolute")
[Link](container);

[Link]("click", function () {
[Link]();
});
}
Funções
Invocação de função no Console (só para testar)
Coloque a função anterior dentro de um html vazio e abra no navegador para testar.
Ao abrir a página, evidentemente ela estará vazia.
Mas abra o Console e digite showNotification(), a notificação deverá aparecer:

O que aconteceu foi o seguinte (sequência de passos indicada pelos quadrados rosa):
Funções
Ao digitar no Console o nome da função com parênteses no final showNotification(), os parênteses
têm um significado especial: é o comando de Invocação da função.
Significa que o navegador web vai imediatamente executar o código da função (passos 1 e 2).
No final, o código da função acaba, e o navegador volta para o Console (linha pontilhada no passo 3).
O undefined que aparece no Console é porque essa função não teve nenhum resultado (ainda veremos
sobre resultado de funções).

Se você esquecer os parênteses, digitando somente showNotification no Console, o


navegador não vai executar a função.
Em vez disso, ele vai mostrar o código dela:

Não mostra o código inteiro porque é grande demais.


Isso que aparece no Console não é uma string, é uma representação do código da
função.
Aquela letra “f” bem no início do resultado quer dizer que showNotification é uma
função.
Funções
Invocação de função no meio do código da aplicação
Começamos ilustrando pelo Console porque é mais simples, mas não é realista.
Na realidade, você estaria programando uma página web que faz alguma coisa, e gostaria de usar a
função showNotification no meio desse código.
Para ver como isso funciona, vamos fazer uma página de lista de tarefas simples. Coloque o seguinte
HTML:

Tarefa: <input />


<br />
<button>Adicionar</button>
<ul></ul>

E o seguinte javascript:

[Link]("button").addEventListener("click", function () {
const text = [Link]("input").value;

showNotification();

const li = [Link]("li");
[Link] = text;

[Link]("ul").appendChild(li);
});

function showNotification() {
// ... código da showNotification,
// trocando a mensagem "Mensagem Aqui"
// por "Sucesso" para fazer mais sentido
}

Esse código funciona assim (explicação em seguida):


Funções

• No passo 1, o usuário clica no botão “Adicionar” e o código do ouvinte de evento começa a ser
executado.

• No passo 2, a segunda linha do código invoca a função showNotification.


Nesse momento, o navegador congela o ouvinte de evento onde estava, e passa a executar o
código da showNotification (passo 3).

• O código da showNotification (passo 4) insere na página a <div> da notificação.

• No passo 5, o código da showNotification acaba.


Então o navegador web volta para o código do ouvinte de evento, que tinha sido previamente
congelado.
Como o navegador está voltando da showNotification de volta para a segunda linha do
ouvinte de evento, dizemos que a showNotification retornou (acabou).

• No passo 6, as 3 últimas linhas do ouvinte de evento são executadas, e elas inserem a <li>
da tarefa na página.
Funções
Por isso que a técnica de invocar funções no meio do código é chamada de Subprogramação:
Se considerarmos que cada função é uma tarefa, podemos interpretar que a showNotification (azul) é
uma subtarefa do ouvinte de evento (vermelho).
Quando a tarefa principal (ouvinte de evento vermelho) invoca a subtarefa (função showNotification
em azul), a tarefa principal fica congelada esperando a subtarefa retornar (terminar).
E pode haver uma “subsubtarefa” também. Não é o caso do exemplo anterior, mas seria algo assim:
• Uma função (tarefa principal, por exemplo um ouvinte de evento) invoca outra função
(subtarefa).
• Essa outra função invoca outra função (“subsubtarefa”).

Quando a tarefa principal invoca a subtarefa, fica congelada esperando a subtarefa ser executada.
Quando a subtarefa invoca a “subsubtarefa”, fica congelada esperando a “subsubtarefa” ser executada.
Aí a “subsubtarefa” termina e retoma a subtarefa.
Depois a subtarefa termina e retoma a tarefa principal.

Quando você invoca funções pré-definidas, como Number("123"), prompt("Digite


uma palavra"), etc, é isso que está acontecendo:
O seu código fica congelado e o código da função é executado até acabar, depois seu
código é retomado de onde parou.
A diferença é que o código das funções pré-definidas fica “oculto” dentro do sistema do
navegador web.
Já o código de funções “customizadas” como a showNotification é você mesmo
quem define.

O código do ouvinte de evento invocou a função showNotification.


Mas isso não tem nenhuma influência sobre o que você já sabe com relação a escopo
de variáveis.
Ou seja, a showNotification não pode acessar as variáveis locais text e li do
ouvinte de evento.
E o ouvinte de evento não pode acessar as variáveis locais container, messageDiv e
closeButton da função showNotification.
Funções
Parâmetro
Da maneira como está, a mensagem de notificação é sempre "Sucesso", essa string está definida dentro
da showNotification.
Mas, e se no ouvinte de evento quisermos fazer uma validação do input, mostrando a mensagem “Tarefa
não pode estar vazia” se o input está vazio, ou então “Tarefa adicionada com sucesso” caso contrário ?
Em outras palavras, queremos poder decidir a mensagem a ser exibida na notificação, como fazíamos
com o alert(《mensagem》).
O código que queremos é o seguinte (ainda não funcional):

[Link]("button").addEventListener("click", function () {
const text = [Link]("input").value;

if (text === "") {


showNotification("Tarefa não pode ser vazia");
} else {
const li = [Link]("li");
[Link] = text;

[Link]("ul").appendChild(li);

showNotification("Tarefa adicionada com sucesso");


}
});

Se você testar esse código, verá que ele não dá nenhum erro, mas também não mostra as mensagens
desejadas, e sim "Sucesso" sempre.
Para funcionar como esperado, a showNotification precisa de um tipo especial de variável chamado de
Parâmetro.
Começando pela solução, o código é o seguinte (comentários indicam as mudanças):
Funções
// Parâmetro `message` no meio dos parênteses.
// É uma variável que vai conter uma string.
function showNotification(message) {
const container = [Link]("div");
[Link] = "absolute";
[Link] = "24px";
[Link] = "24px";
[Link] = "300px";
[Link] = "32px";
[Link] = "8px 24px";
[Link] = "flex";
[Link] = "center";
[Link] = "space-between";
[Link] = "#202124";
[Link] = "white";
[Link] = "4px";
[Link] =
"0 1px 3px 0 rgba(60, 64, 67, 0.302), 0 4px 8px 3px rgba(60, 64, 67, 0.149)";

const messageDiv = [Link]("div");


// Colocar a string na div
[Link] = message;

const closeButton = [Link]("div");


[Link] = "❌";
[Link] = "pointer";

[Link](messageDiv);
[Link](closeButton);

[Link](container);

[Link]("click", function () {
[Link]();
});
}

E o código funciona da seguinte forma:


Se o usuário preencher algo corretamente no input:
Funções

• No passo 1, o evento de clique é disparado e começa a execução do ouvinte de evento

• Passo 2: na última linha do ouvinte de evento, ele invoca a showNotification.

• Passo 3: a string "Tarefa adicionada com sucesso" é atribuída à variável message dentro
da função.
Esse é um código “implícito”, é assim que um parâmetro funciona.
A variável message (parâmetro) é uma variável local normal da função showNotification.
A única característica especial é que seu valor é definido por quem invocou a função (ouvinte
de evento vermelho).

• Passo 4: a showNotification constrói a notificação.

• Passo 5: a showNotification retorna, o ouvinte de evento é retomado.


E ele também termina, já que a invocação da showNotification foi seu último comando.

Agora o outro cenário, se o usuário deixar o input vazio:


Funções

É praticamente a mesma coisa, mas agora a string é "Tarefa não pode ser vazia".
Em resumo: um parâmetro é uma variável declarada no meio dos parênteses da função: function
showNotification(message) { ... }
Apesar de ser tecnicamente a declaração da variável, você não pode colocar let nem const:
• ❌ function showNotification(let message) . Erro de sintaxe !
• ❌ function showNotification(const message) . Erro de sintaxe !

Implicitamente é um let (portanto você pode trocar o valor da variável dentro da função).
Ao invocar a função, você coloca no meio dos parênteses o valor que deseja atribuir à variável:
showNotification("Tarefa adicionada com sucesso").
O propósito de um parâmetro é oferecer, para quem invoca a função, uma oportunidade de passar
informações para dentro dela (nesse caso a mensagem).
Obs: o parâmetro é variável local da função showNotification, portanto somente a função pode
acessar o parâmetro.
Funções
Múltiplos parâmetros
A caixa de notificação está muito monocromática ! É preto sempre !
Vamos permitir alguma variabilidade, da seguinte forma:
• showNotification(《mensagem》, "success") vai mostrar uma notificação com fundo verde claro
(indicando sucesso)
• showNotification(《mensagem》, "error") vai mostrar uma notificação com fundo vermelho
(indicando erro)

Em outras palavras, serão dois parâmetros agora.


O primeiro ainda é a mensagem como antes, e o segundo é uma string indicando a cor de notificação
desejada.
O código necessário é o seguinte (mudanças indicadas por comentários):

[Link]("button").addEventListener("click", function () {
const text = [Link]("input").value;

if (text === "") {


// colocar o valor do segundo parâmetro
showNotification("Tarefa não pode ser vazia", "error");
} else {
const li = [Link]("li");
[Link] = text;

[Link]("ul").appendChild(li);

// colocar o valor do segundo parâmetro


showNotification("Tarefa adicionada com sucesso", "success");
}
});

(código continua na próxima página)


Funções
(continuação do código da página anterior)

// mais um parâmetro. Parâmetros são


// separados por vírgulas
function showNotification(message, type) {
const container = [Link]("div");
[Link] = "absolute";
[Link] = "24px";
[Link] = "24px";
[Link] = "300px";
[Link] = "32px";
[Link] = "8px 24px";
[Link] = "flex";
[Link] = "center";
[Link] = "space-between";
[Link] = "#202124";
[Link] = "white";
[Link] = "4px";
[Link] =
"0 1px 3px 0 rgba(60, 64, 67, 0.302), 0 4px 8px 3px rgba(60, 64, 67, 0.149)";

// mudar a cor do fundo a depender do valor da variável


// `type`
if (type === "success") {
[Link] = "seagreen";
} else if (type === "error") {
[Link] = "tomato";
}

const messageDiv = [Link]("div");


[Link] = message;

const closeButton = [Link]("div");


[Link] = "❌";
[Link] = "pointer";

[Link](messageDiv);
[Link](closeButton);

[Link](container);

[Link]("click", function () {
[Link]();
});
}
Funções
Agora temos 3 tipos de notificação:

Note que a invocação da função pode omitir o segundo parâmetro, o que é entendido como equivalente a
undefined.
Nesse caso, dentro da showNotification a variável type tem valor undefined, por isso não é
executado nem o if (type === "success") nem o else if (type === "error").
Na verdade é possível também omitir ambos os parâmetros, invocando a função como
showNotification().
Nesse caso tanto message quanto type terão valor undefined.
Apesar de não dar nenhum erro, já não faz mais sentido, porque a notificação vai aparecer na tela com
texto “undefined”.
Funções
Cuidado ! Passagem por valor e por referência
Esta seção não é essencial, se quiser pode pular e voltar se tiver problemas com o que será descrito aqui.
Nos exemplos anteriores, os parâmetros da função eram do tipo string.
Ao passar valores string para a função, o que ela recebe é uma cópia do valor original, vamos explicar:
Considere o seguinte código hipotético (não tem nenhuma utilidade prática):

function test(message) {
message += ", more text here";
[Link](message);
}

let text = "some text here";


test(text);
[Link](text);

O passo a passo desse código é o seguinte:

• Passo 1: quando a função é invocada, o valor da variável text é calculado primeiro.


O comando que era test(text) se torna test("some text here").
Essa string é uma cópia do valor da variável text, não é a mesma string (mesmo dado na
memória do computador) que a variável text possui.

• Passo 2: A variável message recebe a string do passo anterior, portanto text e message cada
uma tem uma cópia diferente da string.
Ou seja, quando a função test inicia a executar, estamos assim:
Funções
• Passo 3: a variável message é alterada, e o [Link] mostra "some text here, more
text here".
Ficamos assim:

Note como a variável text não foi impactada.

• Passo 4: depois de a função retornar e o código original ser retomado, o [Link] mostra
"some text here", comprovando que a variável text não foi impactada pelas manipulações
realizadas dentro da função, pois a variável message na função sempre trabalhou com uma
cópia do valor de text.

Ao fato de que o parâmetro message recebe uma cópia do valor fornecido, damos o nome de Passagem
por Valor.
Isso é o que acontece ao trabalhar com os chamados “tipos primitivos”, que são número, string,
booleano, undefined e null.
Porém, ao trabalhar com objetos (e arrays, ou qualquer tipo de objeto), que não são um tipo primitivo,
não é assim que funciona.
Por exemplo, considere o código seguinte (também meramente ilustrativo):

function test(array) {
[Link](100);
[Link](list);
}

const list = [10, 20];


test(list);
[Link](list);

Neste código, list é inicialmente o array [10, 20], e logo em seguida a função é executada.
Neste momento (função iniciou), estamos assim:
Funções

Note que a variável array não é um array independente, mas sim referencia o mesmo array da variável
list.
Por isso ao fazer o [Link](100), ficamos assim:
Funções
E então o [Link] dentro de test imprime [10, 20, 100].
Agora a test retorna e o código original é retomado:

Diferente do que acontecia com strings, a variável list foi sim impactada pelo push realizado dentro da
função test.
O [Link] vai imprimir de novo [10, 20, 100].
Ao fato de que o parâmetro array recebeu não uma cópia de list, mas sim os mesmos dados, damos o
nome de Passagem por Referência.
Isso acontece para o tipo de dados objeto, qualquer tipo de objeto:
• objetos “avulsos”, como {name: "joão", idade: "20"}
• objetos do DOM
• objetos Date
• arrays
• etc.
Funções
Cuidado ! Shadowing
Esta seção não é essencial, se quiser pode pular e voltar se tiver problemas com o que será descrito aqui.
Shadowing (sombreamento) acontece quando uma variável local (seja parâmetro ou não) de uma função
tem o mesmo nome que uma variável global.
Por exemplo no seguinte código hipotético (sem utilidade prática):

function increment(number) {
number++;
[Link](number);
}

const number = 10;


increment(number);
[Link](number);

Note que há uma variável global chamada number, e a função tem uma variável local (nesse caso, um
parâmetro) também chamado number.
Quando o código inicia (antes de começar a função), estamos assim:

Quando a função inicia (antes de executar o number++), estamos assim:


Funções
Note que agora há duas variáveis number:
• Existe a variável global
• E existe a variável local (parâmetro)

Dentro da função, o nome number sempre vai se referir à variável local, por isso dizemos que ela
“sombreia” a variável global (torna a variável global inacessível dentro da função).
Daí o comando number++ incrementa a variável local, a global não é impactada:

E o [Link] imprime 11.


Depois a função retorna e o código original é retomado.
Nesse momento, estamos assim:
Funções
E o [Link] imprime 10.
Se o código tivesse sido:

function increment() {
number++;
[Link](number);
}

const number = 10;


increment(number);
[Link](number);

A única diferença é que a função não tem o parâmetro number.


Nesse código, a palavra number dentro da função se refere à variável global, como você já sabia.
Não tem nenhuma variável local com o mesmo nome da global, por isso não há shadowing.
Logo os [Link] imprimem 11 e 11.
Funções
Valor de retorno
Talvez você já tenha visto, em plataformas de rede social ou blogs, que a data em que uma postagem foi
feita costuma ser exibida de forma “amigável”.
Por exemplo, se hoje é 29 de janeiro de 2024, então uma postagem feita:
• no dia 28 seria exibida como “ontem”
• no dia 27 seria exibida como “há 2 dias”
• no dia 22 seria exibida como “há 1 semana”
• no dia 29 de dezembro de 2023 seria exibida como “há 1 mês”

Suponha que você está programando uma plataforma de blog, onde cada artigo é guardado com a data
na forma ano-mês-dia (como "2024-01-29").
Ao exibir os artigos na página, você gostaria de mostrar a versão “amigável” da data.
Então seria bom ter uma função chamada por exemplo getFriendlyDate (“pegar/calcular data
amigável”), que fizesse a conversão para você.
Ou seja:
• getFriendlyDate("2024-01-29") ⇒ "hoje"
• getFriendlyDate("2024-01-28") ⇒ "ontem"
• getFriendlyDate("2024-01-27") ⇒ "há 2 dias"
• etc.

Em outras palavras, é uma função que faz algo análogo a Number: Number("100") resulta em 100, ou
seja, ela converte o valor pedido para outro valor (string em número).
Já a nossa getFriendlyDate deve converter uma string em outra string.
Para um protótipo, vamos supor que você tem uma <ul> no HTML onde vai exibir os artigos, e seu array
de artigos é:

const articles = [
{ title: "Artigo 1", date: "2024-01-29" }, // Data de hoje
{ title: "Artigo 2", date: "2024-01-28" }, // Data de ontem
{ title: "Artigo 3", date: "2024-01-22" }, // Uma data há mais de uma semana
{ title: "Artigo 4", date: "2024-01-15" }, // Duas semanas atrás
{ title: "Artigo 5", date: "2024-01-01" }, // Quase um mês atrás
{ title: "Artigo 6", date: "2023-12-29" }, // Mais de um mês atrás
{ title: "Artigo 7", date: "2023-12-01" }, // Dois meses atrás
{ title: "Artigo 8", date: "2023-10-29" }, // Três meses atrás
];
Funções
Se a função getFriendlyDate já tivesse sido definida (mas não foi, é justamente isso que vamos fazer
daqui a pouco), o código para exibir esses artigos seria o seguinte:

const ul = [Link]("ul");

for (const article of articles) {


const li = [Link]("li");
const friendlyDate = getFriendlyDate([Link]);
[Link] = `${[Link]} - ${friendlyDate}`;
[Link](li);
}

A página ficaria assim:

Agora vamos ao código da getFriendlyDate.


Primeiro, ela precisa de um parâmetro para a string de entrada, pode se chamar date.
Segundo, ela deve usar alguma lógica para construir a string de resposta.
O código fica assim:
Funções
// a lógica do cálculo é simplificada, não
// se importe muito com a matemática envolvida,
// o importante é que ela monta uma string em
// formato "amigável".
function getFriendlyDate(date) {
// calcular início do dia de hoje.
// usar setHours, etc, para
// voltar à hora 0 de hoje
const todayDate = new Date();
[Link](0);
[Link](0);
[Link](0);
[Link](0);

// objeto Date para a data de entrada


const dateObj = new Date(date + "T00:00:00");

// Diferença em milissegundos
const differenceInTime = [Link]() - [Link]();

const differenceInDays = differenceInTime / (1000 * 3600 * 24);


const differenceInWeeks = differenceInDays / 7;
// Aproximação para cálculo mensal
const differenceInMonths = differenceInDays / 30;

// usar if-else para decidir como exibir o nome


// amigável, e guardar o resultado na variável
// `result`
let result;

if (differenceInDays < 1) {
result = "hoje";
} else if (differenceInDays < 2) {
result = "ontem";
} else if (differenceInDays < 7) {
const rounded = [Link](differenceInDays);
const plural = rounded !== 1 ? "dias" : "dia";
result = `há ${rounded} ${plural}`;
} else if (differenceInWeeks < 4) {
const rounded = [Link](differenceInWeeks);
const plural = rounded !== 1 ? "semanas" : "semana";
result = `há ${rounded} ${plural}`;
} else {
const rounded = [Link](differenceInMonths);
const plural = rounded !== 1 ? "meses" : "mês";
result = `há ${rounded} ${plural}`;
}

// retornar o valor da variável result


return result;
}
Funções
A novidade aqui é o comando return result.
Ele significa que o valor da variável result deve ser considerado como Resultado da função.
Se quiser, experimente invocar essa função no Console para ver seus resultados:

Com a função pronta, a página HTML funciona da seguinte forma (somente a primeira iteração do loop
por simplicidade, explicação em seguida):
Funções
• No passo 1, a iteração inicia criando o objeto <li>.

• No passo 2, é feita a invocação da função getFriendlyDate.


O código dentro do loop fica congelado e inicia o código da função.

• No passo 3, o parâmetro date recebe implicitamente seu valor, e a função começa a executar.

• No passo 4, o código da função é executado e a variável local result adquire o valor "hoje".

• No passo 5, é executado o comando return result.


Como result vale "hoje", esse comando fica return "hoje".
O comando return indica que a string "hoje" deve ser considerada como o Resultado da
função, também chamado Valor de Retorno.
A função termina de executar, e o resultado "hoje" sobe (linha pontilhada) até a linha de
código que chamou a função: const friendlyDate = getFriendlyDate(...).
Como o resultado da função é a string "hoje", essa linha de código se torna: const
friendlyDate = "hoje".

• Nos passos 6 e 7, o código dentro do loop define o texto do <li> e o coloca dentro da lista
<ul>

Na próxima iteração do loop, esse diagrama vai se repetir, claramente com outros valores de data.
Mas o processo será o mesmo: a função getFriendlyDate será invocada, ela retornará o valor da
variável result, o qual será recebido pela variável friendlyDate, etc.
Em resumo, se você quer que sua função tenha um resultado, deve usar o comando return
《resultado》.
O resultado pode ser de qualquer tipo de dados: número, string, booleano, objeto, …

Se a função não tiver um return, o resultado dela é undefined.


Métodos de objeto
Introdução
Você se lembra do objeto Math ?
Ele é um objeto cujas propriedades armazenam funções matemáticas úteis.
Por exemplo [Link] arredonda um número para baixo, [Link] sorteia um número aleatório,
e várias outras.
Agora que você sabe como a subprogramação funciona (i.e. definir funções e invocá-las), pode aproveitar
a capacidade do javascript de definir funções dentro de propriedades de um objeto, como acontece no
Math (onde as propriedades floor e random são funções).
Por exemplo, ao longo desta aula definimos as funções showNotification e getFriendlyDate,
poderíamos definí-las dentro de um objeto para ficar mais organizado (como o Math que reúne várias
funções matemáticas).

Definindo funções como propriedades de um objeto


Seria feito assim:

// objeto `utils` (de "utilitários")


const utils = {
showNotification(message, type) {
const container = [Link]("div");

// ... resto do código ...

if (type === "success") {


[Link] = "seagreen";
} else if (type === "error") {
[Link] = "tomato";
}

// ... resto do código ...


},

getFriendlyDate(date) {
const todayDate = new Date();
[Link](0);
[Link](0);
[Link](0);
[Link](0);

let result;

// ... resto do código ...

return result;
},
};
Métodos de objeto
Observe que não tem a palavra function quando uma função é definida como propriedade de um
objeto.
Outra forma de definir seria assim:

const utils = {
showNotification: function (message, type) {
// código
},

getFriendlyDate: function (date) {


// código
},
};

Onde usamos funções anônimas. Não há diferença prática entre as duas maneiras de definir as funções
dentro do objeto utils.
Você pode até misturar: definir uma função da primeira maneira e a outra da segunda maneira.
Quando funções são definidas como propriedades, elas são geralmente chamadas de Métodos.

Invocando os métodos
Tendo construído o objeto utils, você pode testar que ele funciona pelo Console:

Note que getFriendlyDate é uma propriedade do objeto utils, então fazemos o acesso usando a
notação de ponto que você já conhece.
Como você pode ver, os métodos são invocados da mesma forma que funções globais (funções definidas
no escopo global como antes): você usa a notação de ponto para acessar o método dentro do objeto,
digita os parênteses que significam a invocação, e coloca os valores dos parâmetros dentro dos
parênteses.
Métodos de objeto
Palavra-chave this dentro de um método
A palavra-chave this também funciona dentro de um método, e tem um significado especial.
Para dar um exemplo, vamos lembrar de uma situação típica nas aplicações web feitas até agora,
tomando como referência a aplicação de lista de tarefas que fizemos no final da aula 9.
Há um array global chamado tasks, contendo tarefas onde cada tarefa é um objeto da forma {id:
1706589563604, title: "lavar a louça", priority: "high"}.
Esse array é sincronizado com o Local Storage: quando a página inicia, ele é carregado do Local Storage,
e toda modificação feita durante o uso da página é salva no Local Storage.
A página permite ao usuário adicionar uma nova tarefa, deletar uma tarefa existente, ou trocar a
prioridade.
Nós podemos simplificar todas essas operações usando um objeto tasksController.
Para começar, não haverá mais um array global tasks, mas sim um objeto global tasksController
onde o array de tarefas será uma propriedade:

const tasksController = {
tasks: [], // colocaremos aqui as tarefas
};

Vamos começar simplificando o carregamento do Local Storage:

const tasksController = {
tasks: [],

load: function () {
const tasksLocalStorage = [Link]("tasks");

if (tasksLocalStorage !== null) {


[Link] = [Link](tasksLocalStorage);
}
},
};

Note o uso da palavra-chave this.


Dentro de um método, o significado do this é: o próprio objeto.
Ou seja, substitua mentalmente o this pela variável tasksController:

const tasksController = {
tasks: [],

load: function () {
const tasksLocalStorage = [Link]("tasks");

if (tasksLocalStorage !== null) {


// o `this` é equivalente a `tasksController`
[Link] = [Link](tasksLocalStorage);
}
},
};
Métodos de objeto
O método load carrega os dados do Local Storage e, se eles não vierem null, insere esses dados na
propriedade [Link], que é o array de tarefas.
Assim, quando a página inicia, basta colocar o seguinte código no escopo global para fazer o
carregamento do Local Storage:
[Link]();
Essa linha de código invoca o método load, que por sua vez insere na propriedade
[Link] os dados carregados do Local Storage.
Agora podemos simplificar as operações de criar tarefa, editar prioridade e deletar:

const tasksController = {
tasks: [],

load: function () {
// ...
},

// parâmetros title e priority deve


// ser strings, como "lavar a louça" e "high"
create: function (title, priority) {
[Link]({
id: new Date().getTime(),
title: title,
priority: priority,
});

[Link]("tasks", [Link]([Link]));
},

// id: o id numérico da tarefa, como 1706589563604.


// newPriority: "normal" ou "high"
editPriority: function (id, newPriority) {
// achar o índice da tarefa que tem esse id
const index = [Link]((task) => [Link] === id);

[Link][index].priority = newPriority;

[Link]("tasks", [Link]([Link]));
},

// id: o id numérico da tarefa, como 1706589563604.


delete: function (id) {
// achar o índice da tarefa que tem esse id
const index = [Link]((task) => [Link] === id);

[Link](index, 1);

[Link]("tasks", [Link]([Link]));
},

getTask: function (id) {


const index = [Link]((task) => [Link] === id);

return [Link][index];
},
};
Métodos de objeto
O método create é usado assim: [Link]("lavar a louça", "normal").
Ele insere um novo objeto no array (com um ID calculado na hora), e já salva no Local Storage.
O método editPriority é usado assim: [Link](1706589563604,
"high").
Ele altera a prioridade do objeto tarefa no array, e já salva no Local Storage.
E o método delete é usado assim: [Link](1706589563604).
Ele deleta o objeto tarefa do array, e salva no Local Storage.
Finalmente, o método getTask é usado assim: [Link](1706589563604).
Ele encontra no array o objeto com o ID solicitado, e retorna esse objeto.
Módulos
Módulos no Javascript são uma forma padronizada de importar e exportar
funcionalidades entre arquivos.

Mas o que de fato é um módulo?

É possível fazer uma analogia entre módulos e os capítulos de um livro.

O código Javascript pode ser dividido em várias funções, cada uma com um objetivo específico, tais como
os capítulos de um livro. O conjunto total de funções, trabalhando em conjunto, fazem a totalidade do
sistema.

As principais características de um módulo são:

- autosuficiente: sua saída depende apenas das entradas que recebe

- acoplamento: os usuários do módulo não precisam saber como o módulo foi contruído, mas
apenas os resultados retornados, de acordos com as entradas

- reutilizável: módulos são geralmente construídos para conter uma lógica única dentro do
sistema como, por exemplo, um módulo responsável com conter a lógica necessária a construção
de um botão sendo, portanto, reutilizáveis em vários locais do sistema
Há uma série de benefícios em usar módulos:

- manutenibilidade: por conterem lógica única e serem reutilizáveis, para realizar alterações nas
funcionalidades desempenhadas pelo módulo, basta apenas alterar o seu código interno, por
exemplo, para alterar o comportamento de todos os botões do sistema, basta alterar o módulo
responsável pela construção do botão

- evita o compartilhamento de variáveis globais: como consequência do acoplamento, um


módulo não precisa ter conhecimento de variáveis externas, o que se faz desnecessário o uso de
variáveis globais no sistema

- reusabilidade: como já mencionado, módulos são reusáveis, diminuindo a quantidade de


código duplicado na aplicação

Por dentro do assunto!


O uso de variáveis globais é absolutamente uma má prática em programação. Entre as
razões para essa conclusão, estão:

- variáveis globais podem ser utilizadas em várias locais do sistema, tornando o


entendimento confuso, pois é difícil tem conhecimento de todos os locais que a
utilizam

- variáveis globais podem ser lidas ou modificadas em qualquer parte do sistema,


tornando difícil lembrar ou raciocinar sobre todos os usos possíveis e determinar
qual valor está sendo armazenado em determinado momento da execução do
sistema

- nomes globais estão disponíveis em todos os lugares do código, fazendo com


que você possa, sem saber, acabar usando uma variável global quando pensa
que está usando uma variável local
Criando de módulos
Para utilizar módulos em uma página Web, com Javascript, devemos primeiramente definir o tipo de
script do arquivo .js como module:

<!DOCTYPE html>
<html lang="pt-br">
<head>
...
</head>

<body>
...
<script type="module" src="[Link]"></script>
</body>
</html>

Após isso, basta configurar os arquivos de cada módulo da página e relacioná-los com as declarações
export e import.

Exportação de módulos
A declaração export é utilizada para exportar valores de um módulo Javascript. Os valores exportados
poderão ser importados em outros módulos do sistema.

Há dois de exportações que podem ser utilizadas em um módulo Javascript:

Exportações nomeadas
A declaração export pode ser adicionada antes de cada valor a ser exportado:

// This module is intended to provide basic functions for arithmetic calculations.


// pi stores the value of the mathematical constant π, with 20 places of precision.
export const pi = 3.14159265358979323846;

// add adds two values.


export function add(v1, v2) {
return v1 + v2;
}

// sub subtract v2 from v1.


export function sub(v1, v2) {
return v1 - v2;
}

// mul multiplies two values.


export function mul(v1, v2) {
return v1 * v2;
}

// div divide v1 by v2.


export function div(v1, v2) {
return v1 / v2;
}
O resultado dessa importação é o seguinte objeto de valores:

{
pi: 3.14159265358979323846,
add: function(v1, v2) { ... },
sub: function(v1, v2) { ... },
mul: function(v1, v2) { ... },
div: function(v1, v2) { ... }
}

Da mesma forma, a declaração export pode ser utilizada à parte, como mostrado abaixo:

// This module is intended to provide basic functions for arithmetic calculations.

// pi stores the value of the mathematical constant π, with 20 places of precision.


const pi = 3.14159265358979323846;

// add adds two values.


function add(v1, v2) {
return v1 + v2;
}

// sub subtract v2 from v1.


function sub(v1, v2) {
return v1 - v2;
}

// mul multiplies two values.


function mul(v1, v2) {
return v1 * v2;
}

// div divide v1 by v2.


function div(v1, v2) {
return v1 / v2;
}

export { pi, add, sub, mul, div };

As declarações let, const, var, function ou class podem ser utilizadas antes do export.

A declaração default
A declaração default é utilizada para exportar um único valor para o módulo:

// This module is intended to export the HTML structure for a button.

export default function(label, onClick) {


const e = [Link](
"button");

[Link] = label;
[Link] = onClick;

return e
}
Observe que não foi necessário nomear a função. Porém, também é possível exportar um valor nomeado
como default.

// This module is intended to export the HTML structure for a button.

function buttom(label, onClick) {


const e = [Link](
"button");

[Link] = label;
[Link] = onClick;

return e
}

export default buttom;

A declaração default só pode ser usada uma única vez em um módulo.

Importação de módulos
Valores exportados em módulos Javascript podem ser importados onde forem necessários, com a
utilização da declaração import:

import math from "./modules/[Link]";

A declaração from indica o caminho do arquivo do módulo que está sendo importado. Essa importação
indica que a estrutura de arquivos do projeto é como mostrada abaixo:

├── project
│ ├── modules
│ │ └── [Link]
│ ├── [Link]
│ └── [Link]

A variável math será um objeto com todos os valores exportados pelo módulo math:

{
pi: 3.14159265358979323846,
add: function(v1, v2) { ... },
sub: function(v1, v2) { ... },
mul: function(v1, v2) { ... },
div: function(v1, v2) { ... }
}
Os valores exportados poderão então ser utilizados no arquivo onde foram importados:

import math from "./modules/[Link]";

[Link]([Link]); // 3.14159265358979323846
[Link]([Link](1, 2)); // 3
[Link]([Link](2, 1)); // 1
[Link]([Link](1, 2)); // 2

[Link]([Link](3, 2)); // 1.5

Outra forma de importar os valores exportados é atribuindo cada valor exportado a uma variável, função,
etc., da seguinte forma:

import { pi, add, sub, mul, div } from "./modules/[Link]";

[Link](pi); // 3.14159265358979323846
[Link](add(1, 2)); // 3
[Link](sub(2, 1)); // 1
[Link](mul(1, 2)); // 2
[Link](div(3, 2)); // 1.5

Obseve que cada valor importado passa a ser referenciado com o nome utilizado na importação.

O alias as
A declaração as pode ser utilizado para criar um alias diferente para um valor exportado:

import { pi as PI, add, sub, mul, div } from"./modules/[Link]";

[Link](PI); // 3.14159265358979323846
[Link](add(1, 2)); // 3
[Link](sub(2, 1)); // 1
[Link](mul(1, 2)); // 2

[Link](div(3, 2)); // 1.5

No exemplo acima, a constante pi é agora referenciada como PI.

Um uso muito comum para alias é para importações default:

import * as math from "./modules/[Link]";

O caractere * indica que todos os valores exportados são inseridos no escopo corrente e que podem ser
referenciados com o alias math.
Componentes

Componentes de Software é o termo utilizado para descrever o elemento de software que encapsula uma
série de funcionalidades. É uma unidade independente, que pode ser utilizada com outros componentes
para formar um sistema mais complexo.

No contexto de uma página Web, cada elemento distinto da página (menu, cards, header, rodapé, etc.)
pode ser construído como um componente.

Um bom exemplo é o componente de botão mencionado nesta aula:

// This module is intended to export the HTML structure for a button.

function buttom(label, onClick) {


const e = [Link](
"button");

[Link] = label;
[Link] = onClick;

return e
}

export default buttom;

Toda a lógica necessária a construção de um botão é encapsulada dentro deste componente, que pode
ser utilizado onde for necessário na página Web.
Controle de tempo
A habilidade de gerenciar o tempo de forma precisa e dinâmica é essencial na
criação de aplicações web interativas.

JavaScript, como uma linguagem de programação do lado do cliente, oferece


poderosas funcionalidades para controle temporal, permitindo aos
desenvolvedores criar experiências mais envolventes e responsivas.

Seja para criar animações, agendar tarefas assíncronas, ou controlar eventos em tempo real,
compreender e utilizar eficientemente as capacidades de controle de tempo do JavaScript é fundamental.

Nesta aula, vamos aprender sobre os recursos disponíveis para manipulação de tempo no Javascript.

Métodos para controle de tempo


setTimeout
O método setTimeout cria um temporizador e executa uma função callback quando o cronômetro
expira.

Sua sintaxe é mostrada abaixo:

const timeoutID = setTimeout(


function ([param1], [param2], ...), delay, [param1], [param2], ...)

Por dentro do assunto!


O termo método significa que setTimeout representa uma ação atrelada a algum
objeto. Este objeto é o objeto window do Javascript. Dessa forma, o método
setTimeout pode também ser chamado da seguinte forma:

const timeoutID = [Link](


function ([param1], [param2], ...), delay, [param1], [param2], ...)

Note que o método setTimeout recebe três tipos de parâmetros:

- : é a função callback, chamada pelo setTimeout


function ([param1], [param2], ...)
quando o cronômetro expira
- delay: é o tempo, em milisegundos, decorrido desde a chamada do método setTimeout até a
execução da função callback
- [param1], [param2], ... : são os parâmetros que devem ser passados à função callback
quando for chamada pelo método setTimeout

Um timeoutID é retornado pela chamada do método setTimeout. Esse id é um identificador inteiro


positivo que pode ser utilizado para cancelar a execução do setTimeout.
Por dentro do assunto!
Para refrescar a memória, uma Callback é uma função passada a outra função como
argumento, como mostrado abaixo:

A função
// greeting greetsgreeting é utilizada
a newly arrived como
person. callback na função welcomePerson.
function greeting(name) {
alert(`Olá, ${name}!`);
}

// welcomePerson welcomes a person and greets his arrival.


function welcomePerson(greetingCallback) {
const personName = prompt("Por favor, me diga seu nome!"
)

greetingCallback(personName)
}

A função greeting é utilizada como callback na função welcomePerson.

Como exemplo, imagine que você esteja configurando um botão que, quando clicado chame uma rotina
qualquer. Também imagine que a rotina está suscetível a retornar erros. O botão deverá se comportar da
seguinte forma:

- se a execução da rotina ocorrer com sucesso, o botão deverá mostrar ao usuário a mensagem
"Rotina executada com sucesso!", e fazer com que a mensagem desapareça depois de 3
segundos
- se a execução da rotina resultar em erro, o botão deverá mostrar ao usuário a mensagem "Erro
ao executar a rotina! Tente novamente mais tarde!" , e fazer com que a mensagem
desapareça depois de 5 segundos

A imagem abaixo ilustra melhor a situação:


As seguintes funções poderiam ser utilizadas para implementar essa funcionalidade:

// routine executes the routine.


function routine() {
{ ... }
}

// showSuccessMessage shows the message of success in executing the routine.


function showSuccessMessage() {
{ ... }
}

// showErrorMessage shows the error message in executing the routine.


function showErrorMessage() {
{ ... }
}

// hideMessage hides the displayed message.


function hideMessage() {
{ ... }
}

[Link]("button").addEventListener("click", function() {
try {
routine();
showSuccessMessage();
setTimeout(hideMessage,3000);
} catch {
showErrorMessage();
setTimeout(hideMessage,5000);
}
})

Cancelamento da execução do setTimeout


O cancelamento da execução do setTimeout pode ser realizado com o método clearTimeout, da
seguinte forma:

clearTimeout(timeoutID);

setInterval
O método setTimeout cria um temporizador e executa uma função repetidamente, com um tempo de
espera fixo entre cada execução.

Sua sintaxe é mostrada abaixo:

const intervalID = setInterval(


function ([param1], [param2], ...), delay, [param1], [param2], ...)
Note que o método setInterval recebe três tipos de parâmetros:

- function ([param1], [param2], ...) : é a função callback que é chamada pelo


setInterval a cada expiração do cronômetro
- delay: é o tempo de espera, em milisegundos, entre cada chamada da função callback pelo
setInterval
- [param1], [param2], ... : são os parâmetros que devem ser passados à função callback
quando for chamada pelo método setInterval

Além disso, um intervalID é retornado pela chamada do método setInterval. Esse id é um


identificador inteiro positivo que pode ser utilizado para cancelar a execução do setInterval.

Um bom exemplo de uso para o setInterval é um painel que se responsabiliza em mostrar a cotação
mais recente de uma moeda, tal como na figura abaixo:

fonte: [Link]

Essa cotação pode ser atualizada em um intervalo de tempo fixo, por exemplo, a cada 30 segundos.

As seguintes funções poderiam ser utilizadas para implementar a funcionalidade, considerando que as
informações necessárias são o valor da cota e o instante de tempo em que foi gerada:

// getQuote requests the value of the quote.


function requestQuote() {
{ ... }
}

setInterval(function (){
const quote = requestQuote();

[Link](
"#quote-value").textContent = [Link];
[Link](
"#quote-date").textContent = [Link];
}, 30000);

OBS: As funções acima não representam por completo o fluxo de uma requisição web e o tratamento
necessário para as informações recebidas. Essas funções apenas exemplificam a possível solução para o
problema.

Cancelamento da execução do setTimeout


O cancelamento da execução do setInterval pode ser realizado com o método clearInterval, da
seguinte forma:

clearInterval(intervalID);
O construtor Audio
Para conseguir fazer os exercícios da aula, você precisará conhecer um construtor específico do
Javascript: o construtor Audio.

O construtor Audio retorna um elemento de áudio (HTMLAudioElement) que pode ser anexado ao
documento ou utilizado fora da tela:

const audio = new Audio(url);

O parâmetro opcional url indica a fonte do arquivo de áudio.

Os métodos play e pause do construtor podem ser utilizados, respectivamente, para iniciar e pausar a
execução do áudio.

Você também pode gostar