Identificação
- Duração: 2 horas
- Tipo: teoria aplicada e laboratório
- Entrega: modelo de tarefa com importação e exportação JSON
- Laboratório:
../exemplos/aula-2.5/index.html
Introdução
O que é um objeto?
Um objeto JavaScript reúne informações relacionadas por meio de propriedades:
const task = {
id: 1,
title: "Estudar objetos",
status: "doing",
estimate: 3,
};
Cada propriedade possui uma chave e um valor. Objetos são úteis para representar entidades, configurações e resultados com campos nomeados.
Objeto e array são a mesma coisa?
Não. Um objeto representa normalmente uma entidade:
const task = {
title: "Estudar",
status: "todo",
};
Um array representa uma coleção ordenada:
const tasks = [
{ title: "Estudar", status: "todo" },
{ title: "Praticar", status: "doing" },
];
É comum utilizar arrays de objetos porque temos várias entidades com o mesmo formato.
Objeto e classe são a mesma coisa?
Não. Um objeto é um valor concreto. Uma classe é uma forma de definir como objetos podem ser construídos e quais comportamentos compartilham.
JavaScript permite criar objetos diretamente, sem classe:
const settings = {
theme: "dark",
};
Neste curso, começaremos com objetos literais e funções. Classes serão usadas apenas quando trouxerem uma vantagem clara.
O que é JSON?
JSON significa JavaScript Object Notation. É um formato textual usado para trocar dados:
{
"title": "Estudar objetos",
"status": "doing",
"estimate": 3
}
JSON se parece com um objeto JavaScript, mas não é a mesma coisa:
- objeto JavaScript é um valor em memória;
- JSON é texto;
- JSON exige chaves entre aspas duplas;
- JSON não transporta funções;
- comentários e vírgulas finais não são permitidos no JSON padrão.
JSON é um banco de dados?
Não. JSON é um formato. Ele pode ser enviado por uma API, armazenado em arquivo ou guardado em uma coluna, mas não oferece sozinho consultas, relacionamentos, transações e controle de acesso.
No projeto futuro, o navegador trocará JSON com a API, e a API persistirá os dados no MySQL.
Onde isso aparece no projeto?
Nesta aula, modelaremos uma tarefa com campos consistentes, criaremos cópias sem alterar o objeto original e converteremos o modelo entre objeto e JSON. Dados importados serão validados antes de entrar na aplicação.
Objetivos
Ao final da aula, o aluno deverá conseguir:
- criar e acessar objetos;
- diferenciar objeto, array, classe, JSON e banco de dados;
- adicionar, atualizar e remover propriedades;
- compreender referências de objetos;
- copiar objetos com spread;
- reconhecer os limites de uma cópia rasa;
- utilizar desestruturação e valores padrão;
- aplicar optional chaining e nullish coalescing;
- modelar uma entidade com campos coerentes;
- serializar e interpretar JSON;
- validar dados externos antes do uso.
Pré-requisitos
- Aulas 2.1 a 2.4 concluídas;
- valores, tipos, funções e arrays;
- noções de formulário e DOM;
- navegador, DevTools e editor.
Pergunta orientadora
Como representar uma entidade de forma consistente e trocar seus dados sem confundir objeto em memória com texto JSON?
Roteiro sugerido
| Etapa | Duração |
|---|---|
| Objetos e propriedades | 25 min |
| Referência, cópia e desestruturação | 30 min |
| Modelagem de entidades | 20 min |
| JSON e validação | 25 min |
| Laboratório | 15 min |
| Revisão | 5 min |
1. Objeto literal
const student = {
name: "Ana",
active: true,
completedLessons: 4,
};
As chaves podem ser escritas sem aspas quando são identificadores válidos. Valores podem ser strings, números, booleanos, arrays, outros objetos, funções ou valores ausentes.
2. Acesso com ponto
student.name;
student.active;
A notação de ponto é a opção mais clara quando conhecemos o nome da propriedade.
3. Acesso com colchetes
student["name"];
Colchetes são necessários quando:
- o nome contém caracteres incompatíveis com a notação de ponto;
- a chave está guardada em uma variável;
- a propriedade é calculada dinamicamente.
const selectedField = "completedLessons";
student[selectedField];
Não use:
student.selectedField;
Isso procura literalmente uma propriedade chamada selectedField.
4. Criar e atualizar propriedades
const task = {
title: "Estudar",
};
task.status = "todo";
task.title = "Estudar objetos";
Mesmo declarado com const, o conteúdo do objeto pode mudar. const impede que a
variável passe a apontar para outro objeto:
task = {}; // TypeError
5. Remover propriedades
delete task.temporaryField;
Antes de remover, avalie se o campo deveria ser opcional ou receber null.
Estruturas consistentes são mais fáceis de validar e exibir.
6. Propriedades calculadas
const fieldName = "priority";
const task = {
title: "Estudar",
[fieldName]: "high",
};
O valor de fieldName se torna a chave.
7. Atalhos de propriedade
Quando variável e chave têm o mesmo nome:
const title = "Estudar objetos";
const status = "doing";
const task = {
title,
status,
};
Equivale a:
const task = {
title: title,
status: status,
};
8. Métodos
Uma função armazenada em uma propriedade é um método:
const task = {
title: "Estudar",
describe() {
return `Tarefa: ${this.title}`;
},
};
this depende da forma como a função é chamada. Regras puras que recebem dados por
parâmetro costumam ser mais simples de reutilizar:
function describeTask(task) {
return `Tarefa: ${task.title}`;
}
9. Objetos são acessados por referência
const original = {
title: "Estudar",
};
const alias = original;
alias.title = "Alterado";
console.log(original.title); // "Alterado"
alias e original apontam para o mesmo objeto.
Comparações também usam referência:
{} === {}; // false
const task = {};
task === task; // true
Dois objetos com campos iguais não são automaticamente a mesma referência.
10. Cópia com spread
const original = {
title: "Estudar",
status: "todo",
};
const updated = {
...original,
status: "done",
};
updated é um novo objeto. original.status continua sendo "todo".
A ordem importa:
const wrongOrder = {
status: "done",
...original,
};
O status do original sobrescreve "done".
11. Cópia rasa
Spread copia apenas o primeiro nível:
const original = {
title: "Estudar",
metadata: {
source: "course",
},
};
const copy = { ...original };
copy.metadata.source = "manual";
console.log(original.metadata.source); // "manual"
Para atualizar de maneira imutável:
const updated = {
...original,
metadata: {
...original.metadata,
source: "manual",
},
};
12. structuredClone
Para dados compatíveis, o navegador oferece cópia profunda:
const copy = structuredClone(original);
structuredClone suporta vários tipos, mas não copia funções e pode falhar com
valores não clonáveis. Não utilize JSON.stringify seguido de JSON.parse como
solução geral de cópia profunda, pois tipos e valores podem ser perdidos.
13. Desestruturação
Extrai propriedades para variáveis:
const task = {
title: "Estudar",
status: "doing",
};
const { title, status } = task;
Renomeando:
const { title: taskTitle } = task;
Valor padrão:
const { estimate = 1 } = task;
O padrão é usado quando a propriedade é undefined, não quando é null.
14. Rest em objetos
const task = {
id: 1,
title: "Estudar",
status: "doing",
};
const { id, ...editableFields } = task;
editableFields recebe uma cópia rasa das demais propriedades.
15. Optional chaining
const city = user.address?.city;
Se address for null ou undefined, o resultado será undefined em vez de um
erro.
Não use optional chaining para esconder um campo obrigatório ausente. Ele é útil quando a ausência é realmente permitida.
16. Nullish coalescing
const estimate = task.estimate ?? 1;
O valor padrão é usado apenas para null ou undefined.
Compare:
const valueWithOr = task.estimate || 1;
Se estimate for 0, || escolherá 1, enquanto ?? preservará 0.
17. Verificar propriedades
Object.hasOwn(task, "title");
Isso verifica se a propriedade pertence diretamente ao objeto.
Para listar:
Object.keys(task);
Object.values(task);
Object.entries(task);
Object.entries produz pares [chave, valor], úteis em iteração.
18. Modelagem de uma tarefa
Antes de programar, defina o significado dos campos:
const task = {
id: "task-001",
title: "Estudar objetos",
description: "",
status: "todo",
priority: "planned",
estimateHours: 2,
tags: ["javascript", "curso"],
completedAt: null,
};
Decisões:
ididentifica a entidade;titleé obrigatório;descriptionpode ser string vazia;statusaceita alternativas conhecidas;estimateHoursé número não negativo;tagsé um array de strings;completedAtusanullenquanto não concluída.
Um bom modelo reduz estados ambíguos.
19. Fábrica de objetos
function createTask(input) {
const title = input.title.trim();
return {
id: crypto.randomUUID(),
title,
description: input.description?.trim() ?? "",
status: input.status ?? "todo",
priority: input.priority ?? "planned",
estimateHours: Number(input.estimateHours ?? 0),
tags: input.tags ?? [],
completedAt: null,
};
}
A fábrica centraliza padrões e normalização. Isso não substitui validação.
20. Objeto JavaScript para JSON
const jsonText = JSON.stringify(task);
Formatado para leitura:
const jsonText = JSON.stringify(task, null, 2);
O terceiro argumento define a indentação.
Valores como undefined, funções e símbolos não são representados normalmente em
objetos JSON. Datas viram strings.
21. JSON para valor JavaScript
const parsed = JSON.parse(jsonText);
JSON.parse pode lançar SyntaxError:
try {
const parsed = JSON.parse(jsonText);
} catch (error) {
console.error("JSON inválido", error);
}
O resultado não deve ser confiado apenas porque o texto é JSON válido.
22. Sintaxe válida não garante modelo válido
Este JSON é sintaticamente válido:
{
"title": 42,
"status": "qualquer-coisa"
}
Mas não respeita nosso modelo. Precisamos validar:
function validateTask(value) {
if (typeof value !== "object" || value === null || Array.isArray(value)) {
return false;
}
const hasValidTitle =
typeof value.title === "string" &&
value.title.trim().length >= 3;
const allowedStatuses = ["todo", "doing", "done"];
const hasValidStatus = allowedStatuses.includes(value.status);
return hasValidTitle && hasValidStatus;
}
Em módulos posteriores, usaremos bibliotecas e contratos TypeScript para tornar essa validação mais robusta.
23. JSON não executa código
JSON deve ser interpretado com JSON.parse, nunca com eval:
const value = JSON.parse(jsonText);
Não use:
const value = eval(`(${jsonText})`);
eval pode executar conteúdo malicioso e não é necessário para ler JSON.
24. Datas no JSON
const task = {
createdAt: new Date(),
};
const text = JSON.stringify(task);
A data se torna string ISO. Ao interpretar:
const parsed = JSON.parse(text);
typeof parsed.createdAt; // "string"
Se a aplicação precisa de Date, converta explicitamente após validar o formato.
25. Laboratório guiado
Abra o modelador de tarefas.
Etapa 1 — Crie o objeto
Preencha o formulário e clique em Criar modelo. Observe:
- normalização do título;
- conversão da estimativa;
- transformação das tags em array;
- campos padrão;
- JSON formatado.
Etapa 2 — Atualize sem mutar
Marque a tarefa como concluída. O laboratório cria um novo objeto com spread e preserva a versão anterior.
Etapa 3 — Importe JSON
Edite o JSON e clique em Validar e importar. Teste:
- JSON válido e modelo válido;
- erro de sintaxe;
- título numérico;
- status não permitido;
- objeto ausente ou array no lugar da tarefa.
Etapa 4 — Inspecione o código
Localize:
createTask;completeTask;serializeTask;parseAndValidateTask;validateTask;- atualizações com spread.
26. Erros comuns
Confundir referência com cópia
const copy = original;
Isso cria um alias. Para copiar o primeiro nível:
const copy = { ...original };
Confiar em JSON externo
JSON.parse verifica sintaxe, não regras de negócio. Sempre valide estrutura e
tipos.
Esquecer que JSON é texto
jsonText.title; // undefined
Primeiro:
const task = JSON.parse(jsonText);
task.title;
Usar || quando zero é válido
const estimate = input.estimate || 1;
Use ?? quando apenas ausência deve acionar o padrão.
Espalhar dados não confiáveis sem filtrar
const task = {
...externalValue,
};
Selecione e valide os campos permitidos. Não transporte propriedades arbitrárias para entidades internas.
27. Boas práticas
- modele campos antes de construir a interface;
- use nomes consistentes;
- diferencie ausência, vazio e zero;
- preserve identificadores em atualizações;
- copie cada nível que será alterado;
- valide todo dado externo;
- trate erros de
JSON.parse; - use
JSON.stringifypara serializar; - nunca utilize
evalpara JSON; - não inclua segredos em JSON enviado ao navegador.
28. Exercícios
Exercício 1 — Perfil
Crie um objeto student com nome, e-mail e aulas concluídas.
Exercício 2 — Atualização
Crie uma nova versão de uma tarefa com status: "done" sem alterar a original.
Exercício 3 — Desestruturação
Extraia title e status, renomeando title para taskTitle.
Exercício 4 — Modelo aninhado
Atualize metadata.source copiando corretamente os dois níveis.
Exercício 5 — JSON
Serialise um objeto, interprete o texto e valide os campos obrigatórios.
29. Desafio
Amplie o laboratório:
- permita importar um array de tarefas;
- valide cada item e informe o índice do erro;
- rejeite propriedades desconhecidas;
- adicione
createdAtem formato ISO; - converta a data validada para
Dateapenas na camada de aplicação; - exporte somente campos públicos.
30. Lista de verificação de conclusão
- Sei diferenciar objeto, array, JSON e banco de dados.
- Consigo usar ponto e colchetes.
- Entendo que objetos usam referências.
- Sei criar uma atualização com spread.
- Consigo explicar cópia rasa.
- Uso desestruturação e valores padrão.
- Sei diferenciar
??e||. - Converto objeto para JSON e JSON para objeto.
- Valido dados depois de
JSON.parse. - Não utilizo
eval.
31. Critérios de avaliação
| Critério | Pontos |
|---|---|
| Modelo coerente e documentado | 25 |
| Atualizações sem mutação indevida | 20 |
| Serialização e interpretação JSON | 20 |
| Validação de dados externos | 25 |
| Interface e mensagens de erro | 10 |
| Total | 100 |
Resumo
Nesta aula, aprendemos que:
- objetos representam dados por propriedades nomeadas;
- arrays representam coleções ordenadas;
- objetos são acessados por referência;
- spread cria uma cópia rasa;
- desestruturação facilita acessar campos;
- JSON é texto, não objeto e não banco de dados;
JSON.parseverifica sintaxe, mas a aplicação ainda precisa validar o modelo.
Próxima aula
Na Aula 2.6, separaremos o código em módulos com import e export e trataremos
falhas previsíveis com erros, exceções e estados de recuperação.