Engenharia de IA Aplicada à Programação Web
Aula 4 de 8
Navegar por módulos e aulas
  1. 01 Fundamentos da Web
  2. 02 JavaScript moderno
  3. 03 TypeScript, Git e qualidade
  4. 04 Angular
  5. 05 Node.js, NestJS e APIs
  1. 2.1 Valores, variáveis e tipos
  2. 2.2 Condições e repetições
  3. 2.3 Funções, escopo e closures
  4. 2.4 Arrays e transformação de dados
  5. 2.5 Objetos, JSON e modelagem
  6. 2.6 Módulos e tratamento de erros
  7. 2.7 Promises, async/await e Fetch
  8. 2.8 Armazenamento, testes e projeto

Módulo 2 · Aula 2.4

Arrays e transformação de dados

2 horas Teoria + laboratório JavaScript moderno
Ver fonte Markdown

Identificação

Introdução

O que é um array?

Um array é uma estrutura do JavaScript usada para guardar uma sequência ordenada de valores:

const lessonNames = [
  "Valores e tipos",
  "Condições",
  "Funções",
];

Arrays são úteis quando precisamos representar vários itens relacionados, como tarefas, usuários, mensagens ou aulas.

Array é um banco de dados?

Não. Um array existe na memória enquanto o JavaScript está executando. Ao recarregar a página, seus dados normalmente desaparecem.

Um banco de dados oferece persistência, consultas, controle de concorrência e outras garantias. Mais adiante, utilizaremos MySQL para armazenar informações. Nesta aula, o array será nossa coleção temporária para aprender a transformar dados.

Array e objeto são a mesma coisa?

Um array representa uma coleção ordenada:

const tasks = ["Estudar", "Praticar"];

Um objeto reúne propriedades de uma entidade:

const task = {
  title: "Estudar",
  status: "doing",
};

Na prática, usaremos frequentemente um array de objetos:

const tasks = [
  { title: "Estudar", status: "doing" },
  { title: "Praticar", status: "todo" },
];

Estudaremos objetos com mais profundidade na Aula 2.5.

Por que o primeiro índice é zero?

O primeiro valor está na posição 0:

const colors = ["azul", "verde", "laranja"];

colors[0]; // "azul"
colors[1]; // "verde"
colors[2]; // "laranja"

Por isso, o último índice válido é array.length - 1.

O que significa transformar dados?

Transformar dados é produzir uma nova representação a partir de uma coleção:

  • selecionar somente tarefas abertas;
  • converter tarefas em cartões;
  • somar horas estimadas;
  • ordenar por prioridade;
  • descobrir se existe tarefa crítica.

JavaScript oferece métodos declarativos, como map, filter, reduce e sort. Eles permitem expressar o que desejamos obter sem controlar manualmente cada índice.

Onde isso aparece no projeto?

Nesta aula, uma coleção de tarefas alimentará um painel. Os controles aplicarão um fluxo de filtro, ordenação e cálculo de métricas sem alterar o array original.

Objetivos

Ao final da aula, o aluno deverá conseguir:

  1. criar e acessar arrays;
  2. explicar length e índices;
  3. adicionar e remover itens conscientemente;
  4. percorrer arrays com for...of e forEach;
  5. transformar valores com map;
  6. selecionar valores com filter;
  7. encontrar itens com find;
  8. verificar coleções com some e every;
  9. acumular resultados com reduce;
  10. ordenar dados sem alterar o array original;
  11. explicar mutação e imutabilidade;
  12. encadear transformações legíveis.

Pré-requisitos

  • Aulas 2.1 a 2.3 concluídas;
  • condições, repetições e funções;
  • noções iniciais de objetos;
  • navegador, DevTools e editor.

Pergunta orientadora

Como obter listas e métricas diferentes a partir dos mesmos dados sem destruir a coleção original?

Roteiro sugerido

Etapa Duração
Estrutura, índices e operações básicas 25 min
Iteração e busca 20 min
map, filter e reduce 35 min
Ordenação e imutabilidade 15 min
Laboratório 20 min
Revisão 5 min

1. Criando arrays

const emptyTasks = [];

const taskTitles = [
  "Revisar HTML",
  "Praticar JavaScript",
  "Publicar projeto",
];

Arrays podem tecnicamente misturar tipos:

const mixedValues = ["texto", 42, true, null];

Entretanto, coleções com itens de formato consistente são mais previsíveis:

const estimates = [1, 2, 5, 3];

2. Acesso, tamanho e limites

const tasks = ["A", "B", "C"];

tasks.length; // 3
tasks[0]; // "A"
tasks[tasks.length - 1]; // "C"
tasks[10]; // undefined

length representa a posição seguinte ao último índice, não o último índice.

3. Verificando se é array

Array.isArray([]); // true
Array.isArray({}); // false

typeof não diferencia corretamente:

typeof []; // "object"

Para validar arrays, utilize Array.isArray.

4. Adicionar e remover

Final da coleção

const tasks = ["Estudar"];

tasks.push("Praticar");
const removed = tasks.pop();
  • push adiciona ao final;
  • pop remove e retorna o último item;
  • ambos alteram o array original.

Início da coleção

tasks.unshift("Planejar");
const first = tasks.shift();
  • unshift adiciona no início;
  • shift remove do início;
  • ambos alteram o array.

Alterações no início exigem reposicionar os índices existentes e podem ter custo maior em coleções grandes.

5. Mutação e imutabilidade

Mutação altera o valor existente:

const tasks = ["A", "B"];
tasks.push("C");

Criação imutável produz um novo array:

const tasks = ["A", "B"];
const updatedTasks = [...tasks, "C"];

Imutabilidade ajuda a:

  • comparar versões;
  • evitar alterações distantes e inesperadas;
  • preservar o estado anterior;
  • trabalhar com frameworks que detectam novas referências.

Não significa que todo uso de push seja proibido. Significa compreender se a operação altera a entrada e escolher conscientemente.

6. Cópia rasa com spread

const original = ["A", "B"];
const copy = [...original];

Para objetos internos, a cópia é rasa:

const original = [{ title: "Estudar" }];
const copy = [...original];

copy[0].title = "Alterado";
console.log(original[0].title); // "Alterado"

Os dois arrays são diferentes, mas ainda apontam para o mesmo objeto interno.

7. for...of

for (const task of tasks) {
  console.log(task.title);
}

Use quando deseja controle de fluxo como break, continue ou await.

8. forEach

tasks.forEach((task, index) => {
  console.log(index, task.title);
});

forEach executa um callback para cada item e retorna undefined. Ele é adequado para efeitos, como registrar informações. Não é a escolha para criar um novo array.

Não é possível encerrar um forEach com break.

9. map

map transforma cada item e retorna um novo array com o mesmo tamanho:

const tasks = [
  { title: "Estudar", estimate: 2 },
  { title: "Praticar", estimate: 3 },
];

const titles = tasks.map((task) => task.title);
// ["Estudar", "Praticar"]

Outro exemplo:

const doubledEstimates = tasks.map((task) => task.estimate * 2);

Pergunta para reconhecer map:

Quero converter cada item em outra representação?

10. Erro comum no map

Com chaves, use return:

const titles = tasks.map((task) => {
  return task.title;
});

Sem retorno, o novo array conterá undefined:

const titles = tasks.map((task) => {
  task.title;
});

Retorno implícito:

const titles = tasks.map((task) => task.title);

11. filter

filter mantém os itens cujo callback retorna verdadeiro:

const openTasks = tasks.filter((task) => task.status !== "done");

O resultado pode ter tamanho menor ou igual ao original.

const criticalTasks = tasks.filter(
  (task) => task.priority === "critical",
);

Pergunta para reconhecer filter:

Quero manter apenas os itens que atendem a uma condição?

12. find e findIndex

find retorna o primeiro item encontrado:

const task = tasks.find((item) => item.id === 3);

Se nenhum item atender à condição, retorna undefined.

findIndex retorna o índice:

const index = tasks.findIndex((item) => item.id === 3);

Se não encontrar, retorna -1.

Use find para um item; use filter para uma coleção de itens.

13. some e every

some responde se pelo menos um item atende à regra:

const hasCriticalTask = tasks.some(
  (task) => task.priority === "critical",
);

every responde se todos atendem:

const allTasksDone = tasks.every(
  (task) => task.status === "done",
);

Ambos retornam booleanos e podem parar assim que a resposta estiver determinada.

Em um array vazio:

[].some(() => true); // false
[].every(() => false); // true

O resultado de every pode surpreender. Antes de exibir “todas concluídas”, confira também se existem itens.

14. includes

const allowedStatuses = ["todo", "doing", "done"];
const isAllowed = allowedStatuses.includes("doing");

Para objetos, includes compara a referência:

const task = { id: 1 };
const tasks = [task];

tasks.includes(task); // true
tasks.includes({ id: 1 }); // false

Para procurar por propriedades, utilize find ou some.

15. reduce

reduce acumula os itens em um único resultado:

const totalHours = tasks.reduce((total, task) => {
  return total + task.estimate;
}, 0);

Elementos:

  • total: acumulador;
  • task: item atual;
  • 0: valor inicial.

Evolução:

0 + primeira estimativa
resultado + segunda estimativa
resultado + terceira estimativa

Sempre que possível, informe o valor inicial. Sem ele, arrays vazios podem causar erro e o tipo inicial pode ficar menos evidente.

16. Métricas com reduce

Podemos calcular várias métricas em uma passagem:

const metrics = tasks.reduce(
  (summary, task) => {
    summary.total += 1;
    summary.totalHours += task.estimate;

    if (task.status === "done") {
      summary.completed += 1;
    }

    return summary;
  },
  {
    total: 0,
    completed: 0,
    totalHours: 0,
  },
);

Essa versão altera o objeto acumulador criado para aquela redução. Também poderíamos retornar um novo objeto a cada volta, com custo adicional. O importante é não alterar as tarefas de entrada.

17. sort altera o array

const numbers = [10, 2, 30];
numbers.sort();
// [10, 2, 30] em ordem de texto, não numérica

Para números:

numbers.sort((a, b) => a - b);

E lembre: sort modifica o array.

Ordenação sem alterar a entrada:

const sortedTasks = [...tasks].sort((a, b) => {
  return a.estimate - b.estimate;
});

Ambientes modernos também possuem toSorted, que retorna um novo array:

const sortedTasks = tasks.toSorted(
  (a, b) => a.estimate - b.estimate,
);

Neste curso, a cópia com spread será utilizada enquanto consideramos compatibilidade com navegadores.

18. Ordenação por prioridade

Podemos associar cada prioridade a um peso:

const priorityWeight = {
  critical: 4,
  high: 3,
  planned: 2,
  low: 1,
};

const sorted = [...tasks].sort((a, b) => {
  return priorityWeight[b.priority] - priorityWeight[a.priority];
});

O comparador retorna:

  • valor negativo: a vem antes;
  • zero: mantém equivalência de ordem;
  • valor positivo: b vem antes.

19. Encadeamento

Métodos que retornam arrays podem ser encadeados:

const visibleTitles = tasks
  .filter((task) => task.status !== "done")
  .sort((a, b) => a.estimate - b.estimate)
  .map((task) => task.title);

Leia da esquerda para a direita:

  1. selecione tarefas abertas;
  2. ordene por estimativa;
  3. extraia os títulos.

Evite cadeias longas demais. Use variáveis intermediárias quando elas explicarem as etapas.

20. Fluxo do painel

O laboratório seguirá este fluxo:

tasks
  → filter por status
  → cópia + sort
  → map para elementos visuais
  → reduce para métricas

O array tasks permanece na ordem original. O painel também exibirá essa ordem para que possamos comparar entrada e resultado.

21. Laboratório guiado

Abra o painel de métricas.

Etapa 1 — Filtre

Alterne entre todas, abertas e concluídas. Observe:

  • o número de itens visíveis;
  • a lista resultante;
  • as etapas do fluxo.

Etapa 2 — Ordene

Ordene por prioridade, estimativa e título. Confirme que a ordem original indicada na página não muda.

Etapa 3 — Analise métricas

As métricas são calculadas com reduce sobre os itens visíveis:

  • total;
  • concluídas;
  • horas estimadas;
  • existência de prioridade crítica.

Etapa 4 — Inspecione o código

Localize:

  • filterTasks;
  • sortTasks;
  • calculateMetrics;
  • renderTasks;
  • some, filter, map, reduce e sort.

22. Erros comuns

Confundir item com índice

tasks.map((index) => index.title);

O primeiro parâmetro é o item. Use nomes coerentes:

tasks.map((task) => task.title);

Não retornar no callback

tasks.filter((task) => {
  task.status === "done";
});

Use:

tasks.filter((task) => {
  return task.status === "done";
});

Alterar o original com sort

const sorted = tasks.sort(compareTasks);

Use uma cópia:

const sorted = [...tasks].sort(compareTasks);

Usar map apenas para efeitos

Se não utilizar o array retornado e deseja somente executar um efeito, forEach ou for...of comunica melhor a intenção.

Usar reduce para tudo

reduce é poderoso, mas um filter ou map simples costuma ser mais legível. Escolha o método que expressa a operação.

23. Boas práticas

  • mantenha itens com estrutura consistente;
  • use Array.isArray para validar;
  • escolha métodos pela intenção;
  • não altere entradas de funções de transformação;
  • copie antes de ordenar;
  • forneça valor inicial ao reduce;
  • nomeie acumulador e item claramente;
  • divida fluxos complexos em etapas;
  • trate arrays vazios;
  • preserve regras puras separadas do DOM.

24. Exercícios

Exercício 1 — Títulos

Use map para criar um array somente com os títulos.

Exercício 2 — Pendências

Use filter para selecionar tarefas não concluídas.

Exercício 3 — Busca

Use find para localizar uma tarefa por id.

Exercício 4 — Verificações

Use some para descobrir se existe tarefa crítica e every para verificar se todas estão concluídas.

Exercício 5 — Soma

Use reduce para calcular o total de horas.

Exercício 6 — Ordem imutável

Ordene por título sem modificar a coleção original.

25. Desafio

Amplie o laboratório:

  • adicione filtro por prioridade;
  • combine filtro de status e prioridade;
  • exiba média de horas;
  • crie agrupamento por status com reduce;
  • mantenha a ordem original intacta;
  • mostre um estado vazio quando nenhum item atender aos filtros.

26. Lista de verificação de conclusão

  • Sei explicar array e índice.
  • Sei diferenciar array e banco de dados.
  • Consigo escolher entre map, filter e reduce.
  • Sei quando usar find, some e every.
  • Entendo que sort altera o array.
  • Consigo ordenar uma cópia.
  • Sei explicar cópia rasa.
  • Consigo ler um fluxo encadeado.
  • Testei filtros com resultado vazio.
  • Confirmei que a entrada original foi preservada.

27. Critérios de avaliação

Critério Pontos
Uso correto de métodos de array 30
Métricas com reduce 20
Ordenação sem mutar a entrada 20
Filtros e estados vazios 15
Funções puras e legibilidade 10
Acessibilidade 5
Total 100

Resumo

Nesta aula, aprendemos que:

  • arrays representam sequências ordenadas;
  • índices começam em zero;
  • map transforma, filter seleciona e reduce acumula;
  • find, some e every respondem perguntas sobre a coleção;
  • sort altera o array e deve ser aplicado a uma cópia quando desejamos preservar a entrada;
  • fluxos convertem os mesmos dados em diferentes visualizações e métricas.

Próxima aula

Na Aula 2.5, aprofundaremos objetos, desestruturação, cópias, modelagem de entidades e conversão entre objetos JavaScript e JSON.