Objetos e JSON
BásicoAula 4 de 9 do curso Curso de Programação em JavaScript
O que você vai aprender
- Descreva elementos do mundo real no código como objetos com propriedades nomeadas, leia e altere essas propriedades e compreenda como os objetos são armazenados, copiados e comparados.
- Criar objetos e trabalhar com suas propriedadesEscreva literais de objeto, leia propriedades com as notações de ponto e de colchetes e adicione, altere e exclua propriedades.
- Verificar e percorrer as propriedades de um objetoTeste se uma propriedade existe, liste chaves, valores e pares chave-valor e percorra ou transforme as propriedades de um objeto.
- Compreender referências, cópias e comparaçõesExplique por que objetos são compartilhados por referência, compare objetos corretamente e faça cópias superficiais e profundas.
- Trabalhar com dados aninhadosLeia e processe objetos dentro de objetos e vetores de objetos, proteja-se contra partes ausentes com ?. e ?? e escolha uma estrutura adequada aos dados.
- Criar objetos e trabalhar com suas propriedades
- Escreva métodos que usam os dados do próprio objeto, explique como a palavra-chave this recebe seu valor em cada tipo de chamada e mantenha o this correto quando um método for passado adiante.
- Escrever métodos que usam os dados do próprio objetoDefina métodos com a sintaxe abreviada, use this para ler e atualizar o objeto e chame métodos corretamente.
- Explicar como this recebe seu valorDetermine o valor de this pela forma como uma função é chamada e explique por que funções de seta se comportam de maneira diferente.
- Preservar this ao passar métodos como funções de retornoReconheça quando um método perde seu objeto e corrija isso com uma função envoltória de seta, bind, call ou apply.
- Escrever métodos que usam os dados do próprio objeto
- Extraia valores de objetos e vetores com desestruturação e copie, mescle e colete valores com as sintaxes de espalhamento e rest.
- Desestruturar objetosExtraia propriedades de objetos para variáveis, com renomeação, valores padrão, padrões aninhados e parâmetros de função desestruturados.
- Desestruturar vetores e outros iteráveisExtraia valores por posição, ignore posições e defina valores padrão, troque variáveis e desestruture pares chave-valor em laços.
- Copiar, mesclar e coletar dados com espalhamento e restUse espalhamento para copiar e mesclar objetos e vetores e passar itens de vetor como argumentos, use rest para coletar valores e distinga os dois.
- Desestruturar objetos
- Use Map para coleções de pares chave-valor com chaves de qualquer tipo e Set para coleções de valores únicos, e escolha entre eles e objetos e vetores comuns.
- Armazenar pares chave-valor em um MapCrie e atualize um Map, percorra suas entradas, converta entre Maps e objetos e decida quando um Map é mais adequado que um objeto.
- Manter valores únicos em um SetCrie e atualize um Set, remova duplicatas de vetores e compare coleções com operações de conjuntos.
- Armazenar pares chave-valor em um Map
- Leia e escreva o formato de texto JSON, converta valores JavaScript em JSON com JSON.stringify e texto JSON novamente em valores com JSON.parse e trate os casos em que os dois não correspondem.
- Ler e escrever no formato JSONReconheça JSON válido, explique como ele difere de um literal de objeto JavaScript e identifique erros comuns de sintaxe.
- Converter valores em texto JSON com JSON.stringifyConverta objetos e vetores em cadeias de caracteres JSON, formate a saída, escolha quais propriedades incluir e preveja o que será descartado ou alterado.
- Converter texto JSON em valores com JSON.parseAnalise JSON com segurança, restaure valores como datas com uma função restauradora, verifique os dados analisados e faça conversões de ida e volta por JSON.
- Ler e escrever no formato JSON
Guia de estudo de Objetos e JSON
1Modelar dados com objetos
Um objeto mantém valores relacionados juntos sob nomes, de modo que um registro pode descrever um livro, uma pessoa ou uma leitura. Trabalhar com esses nomes permite alterar um campo, examinar um registro inteiro e organizar listas de registros. Você também acompanhará quais variáveis apontam para o mesmo objeto. Essa distinção importa quando uma alteração aparece em dois lugares, uma cópia contém dados aninhados ou um campo ausente precisa de um valor padrão adequado.
1.1 Criar objetos e trabalhar com suas propriedades
Um objeto agrupa valores relacionados sob nomes. Cada propriedade associa uma chave a um valor. Use um objeto para um registro e um vetor de objetos para uma lista ordenada. Vetores paralelos podem perder seu alinhamento quando apenas um deles é ordenado ou alterado.
Crie e leia um registro
const book = { title: "Dune", pages: 412, available: true };
book.title; // "Dune"
book["title"]; // "Dune"
Valores de propriedades podem ser vetores, objetos ou funções, além de valores primitivos. Chaves são cadeias de caracteres ou símbolos; estes exemplos usam cadeias de caracteres. Chaves de cadeia de caracteres que são identificadores válidos não precisam de aspas. Chaves que contêm espaços ou hífens precisam de aspas: { "release-year": 1965 }. Chaves numéricas tornam-se cadeias de caracteres, então { 1: "a" } tem a chave "1". Literais de objeto permitem uma vírgula final.
O acesso por ponto usa o nome literal após o ponto. O acesso por colchetes avalia uma expressão:
const field = "pages";
book[field]; // 412
book.field; // undefined
A segunda expressão procura uma propriedade chamada "field". Colchetes também permitem usar book["release-year"]. Uma propriedade ausente retorna undefined; continuar o acesso por ela, como em book.author.name, lança um TypeError quando author está ausente.
Altere o conteúdo do objeto
book.author = "Frank Herbert";
book.pages = 896;
delete book.available;
A atribuição adiciona uma propriedade ausente ou substitui um valor existente. A exclusão remove a própria propriedade, então "available" in book agora é falso. const mantém a variável vinculada a esse objeto, mas permite alterações em seu conteúdo.
Para const reading = { city: "Nairobi", tempC: 24.5 };, reading.tempC += 1.5; armazena 26. Em seguida, reading.humidity = 61; adiciona um campo. Com const key = "humidity";, reading[key] lê 61. Um nome como tempC deixa visível a unidade da medida.
Use variáveis em um literal
const name = "Lena";
const age = 29;
const person = { name, age };
const lang = "nl";
const greeting = { [lang]: "Hallo" };
A sintaxe abreviada { name, age } significa { name: name, age: age }. Um nome computado avalia a expressão dentro dos colchetes: greeting tem a propriedade "nl". Sem esses colchetes, { lang: "Hallo" } criaria a chave literal "lang".
Principais conclusões
- Um objeto agrupa valores relacionados em propriedades nomeadas.
- Use colchetes para uma chave armazenada em uma variável ou que contenha um hífen.
- Uma atribuição adiciona ou substitui uma propriedade;
deletea remove. constfixa a variável, não o conteúdo do objeto.- A sintaxe abreviada usa o valor de uma variável; uma chave computada avalia uma expressão.
1.2 Verificar e percorrer as propriedades de um objeto
Verificar se um campo existe é diferente de verificar seu valor. Uma cadeia de caracteres vazia, zero ou false pode ser um valor armazenado perfeitamente válido.
Faça a pergunta certa sobre existência
const item = { stock: 0, note: undefined };
Object.hasOwn(item, "stock"); // true
"note" in item; // true
Boolean(item.stock); // false
Object.hasOwn(obj, key) verifica apenas as propriedades próprias do objeto. O operador in também verifica propriedades herdadas: "toString" in {} é true, enquanto Object.hasOwn({}, "toString") é false. Código mais antigo costuma chamar obj.hasOwnProperty(key).
Uma condição como if (item.stock) testa se o valor é avaliado como verdadeiro. Ela não consegue distinguir um campo ausente de um campo presente que contém zero. O mesmo problema se aplica a "", false, null, undefined e NaN. Até mesmo um valor undefined pode pertencer a uma propriedade existente, como acontece com note acima.
Escolha chaves, valores ou pares
Para const scores = { Ana: 82, Ben: 74, Chen: 91 };, estas funções retornam vetores das propriedades próprias enumeráveis com chaves de cadeia de caracteres:
| Expressão | Resultado |
|---|---|
Object.keys(scores) | ["Ana", "Ben", "Chen"] |
Object.values(scores) | [82, 74, 91] |
Object.entries(scores) | [["Ana", 82], ["Ben", 74], ["Chen", 91]] |
O objeto não tem tamanho como um vetor: scores.length é undefined. Object.keys(scores).length conta três propriedades. Para somar as pontuações, reduza os valores com zero como valor inicial. A soma é 247 e a média é aproximadamente 82,33.
Percorra com ambas as partes disponíveis
let bestName;
let bestScore = -Infinity;
for (const [name, score] of Object.entries(scores)) {
if (score > bestScore) {
bestName = name;
bestScore = score;
}
}
O laço compara 82, 74 e depois 91 com a maior pontuação encontrada até então. Ele termina com "Chen" e 91. O padrão entre colchetes dá nomes às duas partes de cada par.
Um objeto comum não é iterável, então for...of scores lança um TypeError. Object.entries(scores) fornece um vetor iterável. O laço mais antigo for...in produz chaves de cadeia de caracteres e pode incluir propriedades enumeráveis herdadas.
Transforme pares chave-valor novamente em um objeto
const weightsG = { flour: 500, sugar: 250, salt: 5 };
const weightsKg = Object.fromEntries(
Object.entries(weightsG).map(([item, g]) => [item, g / 1000])
);
entries produz pares, map altera cada valor mantendo sua chave e fromEntries reconstrói o registro. O resultado é { flour: 0.5, sugar: 0.25, salt: 0.005 }; weightsG permanece inalterado.
A ordem das propriedades próprias é definida. Chaves de índice de vetor de "0" até "4294967294" aparecem primeiro em ordem crescente; as demais chaves de cadeia de caracteres seguem a ordem de inserção. Um zero à esquerda, como em "01", impede que uma chave seja um índice de vetor. Assim, Object.keys({ b: 1, 2: "x", a: 2, 1: "y" }) resulta em ["1", "2", "b", "a"]. Use um vetor quando as posições tiverem significado.
Principais conclusões
- A existência de uma propriedade e o fato de seu valor ser avaliado como verdadeiro respondem a perguntas diferentes.
Object.hasOwnverifica propriedades próprias;intambém verifica as herdadas.Object.entriesfornece pares chave-valor para laços e transformações.Object.fromEntriesreconstrói um objeto a partir de pares.- Chaves de índice de vetor vêm antes das outras chaves de cadeia de caracteres na ordem das propriedades.
- Conte chaves próprias enumeráveis de cadeia de caracteres com
Object.keys(obj).length.
1.3 Compreender referências, cópias e comparações
Duas variáveis podem se referir a um objeto. Antes de prever uma atualização, decida se o código criou um novo objeto ou copiou uma referência a um objeto existente.
Acompanhe a identidade separadamente dos dados
const p1 = { x: 1 };
const p2 = p1;
p2.x = 99;
p1.x; // 99
p1 === p2; // true
A atribuição copiou a referência. Ambos os nomes acessam a mesma propriedade. A atribuição de valores primitivos funciona de modo diferente: após let a = 5; let b = a; b = 6;, a continua sendo 5.
Objetos são comparados por identidade tanto com === quanto com ==. Dois literais criam objetos separados mesmo quando todos os campos coincidem: ({ x: 1 } === { x: 1 }) é false. Para comparar seus dados, compare as propriedades relevantes. Ter a mesma aparência quando impressos não é uma verificação de identidade.
Passar um objeto para uma função também copia sua referência. Uma função que executa order.status = "shipped"; altera o objeto de quem a chamou. Retornar { ...order, status: "shipped" } cria um novo registro no nível superior.
Distinga const, congelamento e cópia
const cart = { items: 2 }; permite cart.items = 3;, mas reatribuir com cart = {}; lança um TypeError. Object.freeze(cart) impede alterações em suas propriedades próprias. Em modo estrito, tentativas de adicioná-las, removê-las ou sobrescrevê-las lançam um TypeError.
O congelamento é superficial. Se um registro congelado contém outro objeto, os campos desse objeto aninhado ainda podem mudar. Um contêiner congelado e uma estrutura completamente imutável são coisas diferentes.
Acompanhe uma cópia superficial
const settings = { theme: "dark", font: { size: 14 } };
const copy = { ...settings };
copy.theme = "light";
copy.font.size = 18;
O espalhamento cria um novo objeto externo. Seu valor theme é copiado, então alterar copy.theme mantém settings.theme como "dark". Seu valor font é uma referência, copiada para ambos os registros. Atualizar copy.font.size também faz settings.font.size ser igual a 18.
Object.assign({}, settings) também faz uma cópia superficial. Uma cópia superficial separa o registro externo, mantendo a identidade dos objetos e vetores aninhados.
Copie dados aninhados quando precisarem ser independentes
const deep = structuredClone(settings);
deep.font.size = 22;
settings.font.size; // 18
structuredClone copia objetos e vetores aninhados, além de valores compatíveis como Map, Set e Date. Ele também trata referências circulares. O novo font aninhado pode mudar independentemente. Funções não podem ser clonadas dessa maneira: um objeto que contém um método causa um DataCloneError.
Uma conversão de ida e volta por JSON, JSON.parse(JSON.stringify(obj)), copia apenas dados compatíveis com JSON. Ela descarta propriedades de objeto que contêm undefined ou funções, transforma datas em cadeias de caracteres e perde entradas de Map e Set, a menos que você os converta. Escolha uma clonagem para obter dados JavaScript compatíveis e independentes e escolha JSON quando quiser criar uma representação em texto.
Principais conclusões
- Atribuições e chamadas de função copiam referências a objetos.
- Objetos são comparados por identidade, mesmo quando seus campos coincidem.
- Uma cópia superficial compartilha objetos aninhados.
Object.freezeimpede alterações em propriedades próprias, mas é superficial.structuredClonecopia dados aninhados compatíveis e rejeita funções.
1.4 Trabalhar com dados aninhados
Dados aninhados combinam registros e listas. Leia um caminho uma etapa por vez, verificando se cada etapa chega a um objeto, um vetor ou um valor final.
Leia e processe uma lista dentro de um registro
const order = {
id: 1042,
customer: { name: "Sara", city: "Lisbon" },
items: [
{ product: "Tea", qty: 2, unitPrice: 4.5 },
{ product: "Mug", qty: 1, unitPrice: 9 }
]
};
order.customer.city lê "Lisbon". order.items[1].product primeiro seleciona o vetor de itens, depois seu segundo registro e então "Mug". order.items.length é 2.
Os métodos de vetor que você já conhece funcionam com propriedades de registros. map(item => item.product) produz nomes de produtos. filter(item => item.qty > 1) mantém o item de chá. find(item => item.product === "Mug") retorna o registro existente da caneca, então alterar o registro retornado altera o item no pedido.
Para calcular o total, use order.items.reduce((sum, item) => sum + item.qty * item.unitPrice, 0). O primeiro item adiciona 9; o segundo adiciona mais 9, produzindo 18. Calcular um total quando necessário impede que um total armazenado separadamente fique desatualizado quando os itens mudarem.
Leia dados opcionais com uma alternativa de contingência
order.shipping?.date; // undefined
order.customer?.city ?? "unknown"; // "Lisbon"
O encadeamento opcional, ?., para quando o valor imediatamente à sua esquerda é null ou undefined. Um acesso direto order.shipping.date lançaria um TypeError. Use uma verificação em cada parte opcional de um caminho mais longo. O acesso por colchetes e as chamadas também aceitam esse recurso: order.items?.[0] e order.print?.().
O encadeamento opcional é para valores que podem estar ausentes. Campos obrigatórios ainda precisam de verificações ou erros que revelem um registro inválido. Ele não pode aparecer à esquerda de uma atribuição: order.shipping?.date = "2026-05-01" é um erro de sintaxe.
O operador de coalescência nula, ??, usa seu lado direito apenas para null ou undefined. Ele preserva zero, false e "". Para const qty = 0;, qty ?? 1 continua sendo zero, enquanto qty || 1 se torna 1 porque || substitui todo valor avaliado como falso.
Escolha uma estrutura útil
Um vetor de registros é adequado para listagem, filtragem e ordenação. Um objeto indexado por ID permite consulta direta: usersById["u23"].name. Um Map é útil quando chaves de consulta são adicionadas e removidas com frequência.
O JavaScript mais recente oferece Object.groupBy, amplamente disponível desde 2024:
const tasks = [
{ title: "Book flights", status: "done" },
{ title: "Pack", status: "todo" },
{ title: "Renew passport", status: "done" }
];
const grouped = Object.groupBy(tasks, task => task.status);
grouped.done contém dois registros e grouped.todo contém um. O resultado não tem protótipo, então não tem o método herdado toString. Uma alternativa mais antiga constrói os vetores explicitamente para essas chaves de status:
const groupedOlder = tasks.reduce((groups, task) => {
if (!Object.hasOwn(groups, task.status)) {
groups[task.status] = [];
}
groups[task.status].push(task);
return groups;
}, {});
O primeiro registro de cada grupo cria seu vetor. Os registros seguintes são adicionados a esse mesmo vetor. Esse acumulador é um objeto comum; o resultado do método mais recente não tem protótipo. Use nomes e tipos de valor consistentes entre registros; nomes como distanceKm e tempC também mantêm as unidades visíveis.
Principais conclusões
- Leia um caminho aninhado do objeto externo até o valor necessário.
findretorna o registro existente, não uma cópia.?.para em uma parte nula ou indefinida;??fornece uma alternativa para um valor nulo ou indefinido.- Use um vetor para uma lista ordenada e dados indexados por chave para consulta direta.
Object.groupByagrupa registros em vetores sob chaves.- Nomes de campos, tipos e unidades consistentes tornam os registros mais fáceis de processar.
2Dar comportamento aos objetos com métodos e this
Métodos permitem que um objeto combine seus dados com ações que os utilizam. A pequena palavra this conecta uma ação a um objeto, mas seu valor depende de como a função é executada. Você acompanhará chamadas comuns de método, métodos emprestados e funções de retorno e, em seguida, escolherá uma função envoltória ou vinculada quando uma ação precisar manter seu objeto. Os exemplos são executados como módulos, portanto o modo estrito se aplica, salvo quando um exemplo usar explicitamente código não estrito.
2.1 Escrever métodos que usam os dados do próprio objeto
Um método é uma propriedade cujo valor é uma função chamada por meio de um objeto. Ele permite que uma ação use os dados atuais do registro.
Escreva um método com this
const counter = {
count: 0,
increment() {
this.count += 1;
return this.count;
}
};
counter.increment(); // 1
counter.increment(); // 2
A sintaxe abreviada increment() { ... } define uma propriedade cujo valor é uma função comum. Em counter.increment(), o objeto receptor counter se torna this. Cada chamada lê a contagem armazenada, adiciona um e retorna o novo número.
Um count isolado seleciona uma variável, não a propriedade. Sem uma variável correspondente, count += 1 lança um ReferenceError. Use this.count para acessar o campo do objeto receptor.
Leia uma função ou execute-a
counter.increment lê um valor do tipo "function". Os parênteses em counter.increment() executam a função e fornecem seu valor de retorno. Ao passar uma ação para uso posterior, o código que a recebe precisa da função, não do resultado de executá-la agora.
Métodos nativos também usam essa forma de chamada: Math.max(3, 7) retorna 7 e "abc".toUpperCase() retorna "ABC".
Reutilize uma ação
function describe() {
return this.name + " (" + this.year + ")";
}
const film = { name: "Up", year: 2009, describe };
const song = { name: "Hello", year: 2015, describe };
film.describe() retorna "Up (2009)"; song.describe() retorna "Hello (2015)". Usar this permite que a mesma função leia qualquer um dos objetos receptores. Fixar film.name no código a vincularia à variável film.
Retorne o objeto receptor para outra ação
const playlist = {
tracks: [],
add(title) { this.tracks.push(title); return this; },
count() { return this.tracks.length; }
};
playlist.add("Rain").add("Waves").count(); // 2
Cada chamada de add retorna a lista de reprodução, permitindo procurar o próximo método nesse objeto. Retornar um número de add quebraria a cadeia, pois o próximo add seria procurado nesse número.
A conversão comum para JSON omite métodos: converter { name: "Kit", hi() { return 1; } } em texto escreve apenas name. A análise sintática não consegue restaurar código omitido. Registros para salvar ou trocar frequentemente mantêm dados simples e usam funções de processamento separadas.
Principais conclusões
- Um método é uma propriedade cujo valor é uma função chamada por meio de um objeto.
- Em
obj.method(), um método comum usaobjcomothis. - Uma função como valor e o resultado de chamá-la são valores diferentes.
- Retornar
thispode permitir uma chamada de método em seguida. - A conversão comum para JSON omite propriedades cujo valor é uma função.
2.2 Explicar como this recebe seu valor
Para uma função comum, a chamada determina this. Armazenar uma função em um objeto não a vincula permanentemente a esse objeto.
Acompanhe o objeto receptor na chamada
const a = { n: "A", who() { return this.n; } };
const b = { n: "B" };
b.who = a.who;
a.who(); // "A"
b.who(); // "B"
Ambas as propriedades contêm a mesma função. O objeto receptor antes do ponto é diferente, então os resultados são diferentes. O local original da função não determina qual objeto ela lê.
Para uma chamada simples, f(), o modo estrito fornece undefined como this. Módulos JavaScript sempre são executados em modo estrito; um script ou função também pode começar com "use strict";. Uma função comum não estrita chamada de forma simples usa o objeto global, globalThis. Em um navegador, esse objeto global é window.
Reconheça o contexto ao redor de uma função de seta
Uma função de seta não tem this próprio. Ela mantém o this do código ao redor do local onde foi criada. Um literal de objeto não cria um novo contexto de this.
// At the top level of a module:
const user = {
name: "Ida",
hi: () => "Hi, " + this.name
};
Chamar user.hi() lança um TypeError: a função de seta capturou o this do nível superior do módulo, que é undefined. Alterar a chamada para que pareça um método não pode dar um novo objeto receptor à função de seta. No nível superior de um script clássico, o this ao redor é o objeto global.
Use um método comum quando a ação precisar do objeto que faz a chamada. Use uma função de seta dentro desse método quando uma função de retorno precisar manter o contexto do método:
const group = {
title: "Team",
members: ["Ana", "Ben"],
list() {
return this.members.map(m => this.title + ": " + m);
}
};
group.list(); // ["Team: Ana", "Team: Ben"]
list recebe group de sua chamada de método. A função de seta é criada dentro desse método em execução e mantém o mesmo this. Uma função de retorno comum em modo estrito, sem um objeto receptor fornecido, receberia undefined, então this.title falharia nela.
Use uma ordem de decisão
Quando encontrar uma chamada, primeiro identifique a função que está sendo chamada:
- Uma função de seta mantém o
thisao seu redor;call,applyebindnão podem substituí-lo. - Uma função comum vinculada mantém seu
thisvinculado, mesmo comcallouapply. - Uma função comum não vinculada chamada com
callouapplyusa othisfornecido. - Uma chamada comum
obj.method()usaobj. - Uma chamada simples de função comum usa
undefinedem modo estrito ou o objeto global em modo não estrito.
Funções de retorno podem receber um objeto receptor de quem as chama. Por exemplo, um ouvinte de evento DOM comum registrado com addEventListener recebe como this o elemento no qual está registrado. Veja como o código que recebe uma função de retorno a chama antes de supor que se trata de uma chamada simples.
Principais conclusões
- Uma função comum recebe
thisde sua chamada, então emprestar um método muda seu objeto receptor. - Uma chamada simples em modo estrito usa
undefinedcomothis. - Uma função de seta mantém o
thisao redor do local onde foi criada. - Um objeto receptor vinculado tem precedência sobre chamadas posteriores com
callouapply. - Uma função de seta dentro de um método comum pode manter o
thisdesse método.
2.3 Preservar this ao passar métodos como funções de retorno
Extrair um método de seu objeto preserva a função, mas perde a expressão de chamada original. Uma função de retorno deve ser chamada de uma forma que forneça o objeto de que ela precisa.
Diagnostique um método desvinculado
const counter = {
count: 0,
increment() {
this.count += 1;
return this.count;
}
};
const inc = counter.increment;
inc(); // TypeError in strict mode
inc() é uma chamada simples, então this é undefined. A leitura de this.count falha antes que um incremento possa ocorrer. Em código não estrito, uma chamada simples usa o objeto global e pode escrever em um count global; ela não acessa o contador.
O mesmo problema aparece em funções de retorno de vetores. [1, 2].map(counter.increment) fornece uma função a map sem seu objeto receptor original. Os valores do vetor passados como argumentos não fornecem this.
Envolva a chamada do método
const results = [1, 2].map(() => counter.increment());
// results is [1, 2]; counter.count is 2
A função de retorno é uma função de seta que faz uma chamada normal de counter.increment(). Essa chamada tem um objeto receptor. A função envoltória ignora deliberadamente os valores passados por map; cada chamada apenas incrementa uma vez. Essa forma é conveniente quando a função de retorno é necessária em um único uso.
Vincule uma função reutilizável
Começando com um novo contador em zero:
const boundInc = counter.increment.bind(counter);
const results = [1, 2].map(boundInc);
// results is [1, 2]; counter.count is 2
bind retorna uma nova função; ele ainda não chama o método. A nova função mantém counter como seu objeto receptor. Vinculá-la novamente a outro objeto não pode substituir esse receptor. Cada chamada de bind cria uma função distinta, então salve o resultado quando o código precisar reconhecer exatamente a mesma função de retorno mais tarde.
A vinculação também pode fixar argumentos iniciais. function multiply(a, b) { return a * b; } seguido de const double = multiply.bind(null, 2); faz double(21) retornar 42. null ocupa a posição do objeto receptor porque essa função não usa this; 2 ocupa seu primeiro parâmetro comum.
Execute uma vez com call ou apply
function describe(unit) {
return this.value + " " + unit;
}
describe.call({ value: 12 }, "kg"); // "12 kg"
describe.apply({ value: 12 }, ["kg"]); // "12 kg"
Ambas as formas executam imediatamente com o objeto receptor escolhido. call fornece os argumentos separadamente; apply os fornece em um vetor. O contexto de uma função de seta é fixado pelo que a envolve, então esses métodos não podem substituir seu this.
Passar counter.increment() como função de retorno executa o método imediatamente e passa o número retornado. Esse não é o tipo de função de que map precisa. Em um registro de evento como button.addEventListener("click", counter.increment()), o contador muda imediatamente e o ouvinte numérico causa um TypeError. Passe uma função como valor, uma função envoltória de seta ou uma função vinculada armazenada.
Principais conclusões
- Desvincular um método remove seu objeto receptor original.
- Uma função envoltória de seta pode fazer a chamada de método necessária mais tarde.
bindcria uma função com um objeto receptor fixo e argumentos iniciais opcionais.calleapplyexecutam imediatamente; seus formatos de argumentos são diferentes.- Argumentos usados como funções de retorno devem ser funções, não o resultado numérico da execução de um método.
3Extrair e combinar dados com desestruturação, espalhamento e rest
A desestruturação dá nomes a partes selecionadas de um objeto ou de uma coleção ordenada. O espalhamento constrói valores a partir de partes existentes, enquanto rest reúne as partes restantes. Essas formas frequentemente aparecem juntas em funções que recebem opções ou retornam registros atualizados. Observar sua posição com atenção permite prever quais variáveis existem, quais valores padrão se aplicam e se dados aninhados são compartilhados com o original.
3.1 Desestruturar objetos
A desestruturação de objetos lê campos nomeados para variáveis locais. Ela seleciona valores sem copiar todo o registro de origem.
Faça a correspondência e renomeie
const book = { title: "Dune", pages: 412 };
const { pages, title: bookTitle, rating: stars = 0 } = book;
A correspondência usa nomes de propriedades, não sua ordem. Isso declara pages como 412, bookTitle como "Dune" e stars como 0. Não declara variáveis title ou rating: o nome após os dois-pontos é a variável local de destino.
Um campo ausente fornece undefined. Um valor padrão substitui apenas undefined, preservando null, zero, false e cadeias de caracteres vazias. const { a = 5 } = { a: null }; deixa, portanto, a como null.
Acompanhe campos aninhados
const data = {
location: { name: "Oslo" },
current: { tempC: -3, windKph: 18 }
};
const {
location: { name },
current: { tempC, windKph: wind }
} = data;
As variáveis declaradas são name, tempC e wind, com os valores "Oslo", -3 e 18. Os nomes externos location e current selecionam caminhos; eles não se tornam variáveis.
Um objeto externo ausente faz uma leitura aninhada falhar. const { shipping: { date } } = {}; lança TypeError. Forneça um valor padrão externo quando esse campo puder ser undefined:
const { shipping: { date } = {} } = {};
// date is undefined
Isso não substitui shipping quando seu valor é null. Desestruturar null ou undefined diretamente também lança um erro, então a origem deve ser utilizável antes do início da extração.
Receba opções nomeadas
function formatUser({ name, age = "unknown" }) {
return name + ", " + age;
}
formatUser({ name: "Mo" }) retorna "Mo, unknown". Reordenar os campos em { age: 40, name: "Ines" } ainda retorna "Ines, 40". Chamar formatUser sem argumento falha porque não há objeto para desestruturar. Um valor padrão para todo o parâmetro permite essa chamada:
function greet({ name = "guest" } = {}) {
return "Hi, " + name;
}
greet(); // "Hi, guest"
O valor padrão externo trata um argumento omitido; o valor padrão interno trata um nome ausente. Passar null ainda causa uma falha. Para atribuir valores a variáveis existentes, envolva uma instrução com padrão de objeto entre parênteses: let x, y; ({ x, y } = { x: 4, y: 7 });. Caso contrário, as chaves iniciais são interpretadas como um bloco de instruções.
Principais conclusões
- Padrões de objeto fazem a correspondência de propriedades pelo nome.
- Os dois-pontos renomeiam a variável; eles não alteram a chave de origem.
- Valores padrão substituem
undefined, inclusive em propriedades ausentes, e preservamnull. - Padrões aninhados precisam de um objeto utilizável em cada nível.
- Um valor padrão para todo o parâmetro e um valor padrão para uma propriedade tratam valores ausentes diferentes.
- Parênteses permitem que um padrão de objeto atribua valores a variáveis existentes.
3.2 Desestruturar vetores e outros iteráveis
A desestruturação de vetores lê valores por posição de um iterável. As vírgulas controlam quais valores são selecionados; os nomes das variáveis não escolhem posições.
Selecione ou ignore posições
const medals = ["gold", "silver", "bronze"];
const [first, second] = medals;
const [, , third] = medals;
As variáveis recebem "gold", "silver" e "bronze". Posições vazias consomem valores sem declarar variáveis. Um nome além dos valores disponíveis recebe undefined. Valores padrão substituem apenas undefined:
const [p, q = 10] = [1]; // p is 1; q is 10
const [r = 10] = [null]; // r is null
Reúna os valores restantes
const [head, ...tail] = [1, 2, 3, 4];
// head is 1; tail is [2, 3, 4]
O elemento rest final cria um novo vetor, vazio quando nada resta. Ele deve ser o último. Quaisquer valores que sejam objetos dentro desse vetor mantêm suas identidades; coletá-los não os clona profundamente.
Leia um par retornado ou troque variáveis
function minMax(nums) {
return [Math.min(...nums), Math.max(...nums)];
}
const [lo, hi] = minMax([4, 9, 1]);
// lo is 1; hi is 9
Quem chama segue a ordem definida pela função que retorna os valores. Para muitos campos de resultado, propriedades nomeadas em objetos evitam ter de lembrar posições.
Com let x = 1, y = 2;, [x, y] = [y, x]; troca os valores das variáveis. O vetor à direita é avaliado como [2, 1] antes de qualquer atribuição, preservando os dois valores antigos sem uma variável temporária.
Extraia valores de outros iteráveis
Cadeias de caracteres e Sets também podem ser desestruturados: const [initial] = "Zoe"; resulta em "Z". Sets fornecem valores na ordem de inserção. Entradas de Map são pares ordenados:
const distances = new Map([["park", 2], ["lake", 5]]);
for (const [place, distanceKm] of distances) {
console.log(place, distanceKm);
}
O laço recebe um par e, em seguida, o padrão separa sua chave e seu valor. Object.entries fornece a mesma estrutura de par.
Um objeto comum não é iterável, então const [name] = { name: "Ana" }; lança TypeError. Use chaves para selecionar seu campo nomeado: const { name } = { name: "Ana" };. Colchetes exigem uma sequência de valores; chaves selecionam propriedades pelo nome.
Principais conclusões
- Padrões de vetor fazem a correspondência por posição, e posições vazias ignoram valores.
- Uma posição ausente resulta em
undefined, a menos que um valor padrão o substitua. - Um elemento rest final coleta os valores restantes em um novo vetor.
- Padrões de vetor também funcionam em cadeias de caracteres, Sets e entradas de Map.
3.3 Copiar, mesclar e coletar dados com espalhamento e rest
Os três pontos, ..., têm duas funções relacionadas. O espalhamento expande dados existentes em um valor ou uma chamada. Rest reúne valores em uma variável declarada por um padrão ou parâmetro.
Mescle na ordem de prioridade
const defaults = { lang: "en", units: "metric", alerts: true };
const user = { lang: "pt", alerts: false };
const options = { ...defaults, ...user };
// { lang: "pt", units: "metric", alerts: false }
O espalhamento de objetos copia propriedades próprias enumeráveis. Quando uma chave aparece novamente, prevalece o valor posterior. Colocar user antes de defaults sobrescreveria as configurações do usuário. Espalhar null ou undefined em um objeto não adiciona nada.
Cópias por espalhamento são superficiais. Se um registro aninhado mudar, copie esse nível também:
const settings = { theme: "dark", font: { size: 14, family: "serif" } };
const next = {
...settings,
font: { ...settings.font, size: 18 }
};
O espalhamento externo preserva theme. O interno preserva family enquanto substitui size. settings.font.size permanece 14 porque o registro aninhado alterado é novo.
Substitua um registro em uma lista
const todos = [{ id: 1, done: false }, { id: 2, done: false }];
const updated = todos.map(t =>
t.id === 2 ? { ...t, done: true } : t
);
map cria um novo vetor. O item correspondente se torna um novo objeto, então updated[1].done é true enquanto todos[1].done continua sendo false. O primeiro item, inalterado, é reutilizado: updated[0] === todos[0] é true. Atualizações independentes não exigem copiar registros inalterados.
Expanda valores iteráveis
Em um literal de vetor ou chamada de função, o espalhamento extrai valores de um iterável. [...a, ...b] junta seus valores em um novo vetor. Math.max(...[4, 9, 1]) passa três argumentos e retorna 9. Um objeto comum não pode ser expandido em um vetor: [...{ a: 1 }] lança um TypeError. O espalhamento de objetos e o espalhamento de iteráveis usam regras diferentes para determinar o que leem.
Reúna argumentos ou propriedades restantes
function total(...nums) {
return nums.reduce((sum, n) => sum + n, 0);
}
total(2, 3, 5); // 10
total(); // 0
Um parâmetro rest recebe um vetor verdadeiro, mesmo quando não recebe valores. Ele deve ser o último parâmetro, e só pode haver um. O antigo objeto arguments não é um vetor verdadeiro. Funções de seta não têm arguments próprio, embora possam ler a vinculação de uma função comum que as envolve.
A sintaxe rest de objetos coleta propriedades próprias enumeráveis que ainda não foram selecionadas:
const userRecord = { id: 8, name: "Rae", password: "x9!k" };
const { password, ...publicUser } = userRecord;
// publicUser is { id: 8, name: "Rae" }
Isso cria um novo registro e deixa a origem inalterada. A propriedade rest deve ser a última. Observe a posição para distinguir as funções: três pontos em um literal ou chamada espalham valores para fora; três pontos em uma lista de parâmetros ou em um destino de desestruturação reúnem valores.
Principais conclusões
- Propriedades posteriores prevalecem quando espalhamentos de objetos têm chaves em comum.
- Copie cada nível aninhado que precisa mudar de forma independente.
- O espalhamento em vetores e chamadas precisa de um iterável.
- Rest coleta argumentos, itens ou propriedades restantes e deve vir por último.
- Uma atualização com map pode copiar um registro alterado enquanto reutiliza registros inalterados.
- Parâmetros rest são vetores verdadeiros; o antigo objeto
argumentsnão é.
4Armazenar coleções com Map e Set
Algumas coleções precisam de chaves que sejam objetos ou números, e outras precisam manter cada valor apenas uma vez. Map e Set expressam essas necessidades diretamente. Você criará entradas, testará a pertinência, acompanhará a ordem de inserção e converterá coleções em vetores ou objetos quando outra operação precisar dessa estrutura. A igualdade continua sendo importante: dois registros com campos iguais podem continuar sendo dois valores separados em qualquer uma das coleções.
4.1 Armazenar pares chave-valor em um Map
Um Map armazena associações entre chaves e valores. Diferentemente das chaves de cadeia de caracteres de um objeto comum, uma chave de Map pode ser um número, um objeto ou outro valor sem ser convertida em uma cadeia de caracteres.
Crie e mantenha entradas
const stock = new Map();
stock.set("apples", 12).set("pears", 7);
stock.get("apples"); // 12
stock.has("kiwis"); // false
stock.size; // 2
set adiciona uma entrada ou substitui seu valor e retorna o Map para encadeamento. get retorna undefined para uma chave ausente; use has para distinguir isso de uma entrada que armazena undefined. delete(key) retorna se removeu uma entrada, e clear() esvazia a coleção.
A notação de colchetes usa uma área de armazenamento diferente: stock["plums"] = 5; adiciona uma propriedade comum ao objeto Map. Ela não cria uma entrada visível para get, has ou size. Use os métodos de Map para entradas.
Mantenha tipos e identidades das chaves
m.set(1, "number"); m.set("1", "text"); cria duas entradas. As chaves 1 e "1" de um objeto comum se refeririam a uma única propriedade. Chaves de Map são comparadas como em ===, exceto que NaN corresponde a si mesmo e zeros com sinais diferentes compartilham uma chave.
const person = { id: 1 };
const notes = new Map([[person, "ready"]]);
notes.get(person); // "ready"
notes.get({ id: 1 }); // undefined
A segunda consulta cria um novo objeto. Campos iguais não fazem dele a mesma chave. Guarde e reutilize a referência ao objeto original quando usar um objeto como chave.
Percorra e converta pares
for (const [name, count] of stock) {
console.log(name, count);
}
Um Map fornece pares [key, value] na ordem da primeira inserção. Substituir um valor não muda a posição de sua chave. keys(), values() e entries() retornam iteradores que você pode percorrer ou espalhar em vetores. forEach passa à sua função de retorno primeiro o valor e depois a chave.
new Map(Object.entries(obj)) transforma as entradas de um registro em um Map. Object.fromEntries(map) cria um objeto; use-o quando as chaves forem cadeias de caracteres, pois chaves de objeto não conseguem preservar todos os tipos de chave de Map. [...map] cria um vetor de pares, útil para salvar as entradas de um Map como JSON.
Conte chaves que mudam
const words = "the cat saw the dog and the bird".split(" ");
const counts = new Map();
for (const word of words) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
A primeira ocorrência começa em zero e depois soma um. Ocorrências posteriores leem e aumentam a contagem armazenada. counts.get("the") é 3 e counts.size é 6: o tamanho conta palavras distintas, não todas as oito ocorrências.
Escolha um objeto comum para um registro com campos conhecidos, especialmente dados compatíveis com JSON. Escolha um Map para chaves que mudam, verificações frequentes de tamanho ou chaves cujos tipos precisam ser preservados. O Map.groupBy mais recente preserva os tipos das chaves de grupo:
const owner = { name: "Ari" };
const jobs = [{ owner, done: false }, { owner, done: true }];
const byOwner = Map.groupBy(jobs, job => job.owner);
byOwner.get(owner).length; // 2
Em código mais antigo, percorra jobs em um laço. Para cada owner, use has e set para criar um vetor de grupo uma vez e depois get(owner).push(job) para adicionar o registro. Manter owner como chave de objeto distingue responsáveis diferentes mesmo quando seus campos de nome são iguais. Um WeakMap pode associar metadados a objetos sem manter vivos objetos usados como chaves que, de outro modo, seriam inalcançáveis. Ele não permite iteração nem tem tamanho. WeakMaps modernos também aceitam símbolos não registrados como chaves.
Principais conclusões
- Chaves de Map preservam seus tipos e comparam objetos por identidade.
- Use
set,get,hasedeletepara entradas, não a notação de colchetes. sizeconta entradas e a iteração segue a ordem de inserção das chaves.- Maps são convertidos por meio de pares chave-valor.
- Um WeakMap pode manter metadados de objetos sem manter vivos os objetos usados como chaves.
Map.groupBypreserva os tipos das chaves de grupo em uma API de agrupamento mais recente.
4.2 Manter valores únicos em um Set
Um Set armazena valores únicos. Suas principais questões são se um valor está presente e como duas coleções se sobrepõem.
Adicione e teste valores
const tags = new Set(["js", "css", "js"]);
tags.size; // 2
tags.add("html");
tags.has("css"); // true
Adicionar um valor existente não altera nada. add retorna o Set para encadeamento. delete(value) retorna se o valor foi removido, enquanto clear() remove todos os valores. O construtor recebe um iterável: use new Set([1, 2, 3]). new Set(1, 2, 3) lança um TypeError porque sua primeira entrada não é iterável. Uma cadeia de caracteres é iterável, então new Set("hello") contém "h", "e", "l" e "o".
Um Set não tem posições indexadas. tags[0] é undefined. Percorra-o com for...of, chame forEach ou converta-o em um vetor para operações como map e filter. A iteração segue a ordem de inserção; remover um valor e adicioná-lo novamente o coloca no fim.
Remova duplicatas sem ordenar
const unique = [...new Set([3, 1, 3, 2, 1])];
// [3, 1, 2]
O Set mantém a primeira ocorrência de cada valor. O espalhamento fornece esses valores em um vetor. Array.from(set) faz a mesma conversão.
Os valores são comparados como em ===, exceto que NaN corresponde a si mesmo; zeros com sinais diferentes contam como um valor. Valores que são objetos são comparados por identidade: new Set([{ id: 1 }, { id: 1 }]).size é 2. Para manter um registro por ID, construa um Map indexado por esse ID e depois leia seus valores. Registros posteriores com o mesmo ID substituem os anteriores, porque set atualiza uma entrada existente.
Para testes de pertinência repetidos em coleções grandes, um Set evita a busca um a um feita por includes em um vetor. Use-o quando a presença for mais importante que a posição.
Compare duas coleções
Métodos mais recentes de Set estão disponíveis nos principais navegadores desde 2024. Com a contendo 1, 2, 3, 4 e b contendo 3, 4, 5:
| Operação | Significado | Valores resultantes |
|---|---|---|
a.union(b) | Em qualquer uma das coleções | 1, 2, 3, 4, 5 |
a.intersection(b) | Em ambas | 3, 4 |
a.difference(b) | Em a, mas não em b | 1, 2 |
a.symmetricDifference(b) | Em exatamente uma | 1, 2, 5 |
Essas operações retornam novos Sets. isSubsetOf verifica se cada valor está na outra coleção. isSupersetOf verifica a relação inversa de inclusão. isDisjointFrom verifica se as coleções não compartilham valores. Os três retornam booleanos. Por exemplo, new Set([3, 4]).isSubsetOf(a) é true. A diferença tem uma direção: os valores em b, mas não em a, seriam apenas 5.
Em um ambiente mais antigo, uma interseção pode ser escrita como new Set([...a].filter(x => b.has(x))).
A chamada comum JSON.stringify(set) produz "{}", perdendo os valores armazenados. Converta para um vetor antes de escrever JSON e depois use new Set(parsedArray) ao ler. Um WeakSet pode marcar objetos como processados sem manter vivos objetos que, de outro modo, seriam inalcançáveis. Ele não pode ser percorrido. WeakSets modernos também aceitam símbolos não registrados.
Principais conclusões
- Um Set armazena cada valor distinto uma vez e testa sua presença com
has. - Converta um Set em vetor para usar índices ou métodos de vetor.
- Valores que são objetos permanecem distintos, a menos que suas referências correspondam.
- União, interseção, diferença e diferença simétrica respondem a perguntas diferentes sobre pertinência.
- A diferença depende de qual Set vem primeiro.
- Converta valores de Set em um vetor antes de escrever JSON.
- WeakSet pode marcar objetos sem mantê-los vivos.
5Converter dados para JSON e de JSON
JSON transporta dados estruturados como texto. Converter entre esse texto e valores JavaScript em uso só é útil quando você sabe quais informações sobrevivem à conversão. Você reconhecerá JSON válido, controlará como os valores são escritos e tratará entradas malformadas ao lê-las. Uma análise sintática bem-sucedida também exige uma verificação da estrutura dos dados antes que o programa dependa de seus campos; um texto válido por si só não garante os dados esperados.
5.1 Ler e escrever no formato JSON
JSON, abreviação de JavaScript Object Notation, é um formato de texto independente de linguagem para dados estruturados. Um objeto é um valor JavaScript em uso; JSON é texto que pode descrever esse valor.
Reconheça os seis tipos de valor
JSON aceita objetos, vetores, cadeias de caracteres, números, booleanos e null. Qualquer um deles pode ser o valor de nível superior. O texto 42 é JSON válido mesmo sem chaves. JSON não tem representação para funções, undefined, datas como um tipo distinto, Map, Set, NaN ou Infinity.
{
"name": "Amara",
"age": 34,
"languages": ["en", "yo"],
"address": null,
"member": true
}
As mesmas ideias estruturais aparecem em literais JavaScript, mas a forma permitida é mais restrita. JSON é usado em configurações e na troca de dados. JSON trocado entre sistemas usa a codificação UTF-8 e o tipo de mídia application/json; arquivos JSON usam a extensão .json.
Aplique as regras de sintaxe
Toda chave de objeto deve ser uma cadeia de caracteres entre aspas duplas. Cadeias de caracteres também exigem aspas duplas. Vírgulas separam propriedades ou itens de vetor, mas nenhuma vírgula pode vir após o último. Comentários são proibidos. Espaços em branco entre valores e sinais de pontuação são permitidos.
| Texto | Por que falha |
|---|---|
{name: "Amara"} | A chave não tem aspas duplas. |
{'name': 'Amara'} | Aspas simples não delimitam cadeias de caracteres JSON. |
{"a": 1,} | Não há propriedade após a vírgula final. |
{"a": undefined} | Undefined não é um valor JSON. |
Números usam notação decimal. 1.5e3, -0.25 e 0 são válidos. 07, +1 e 0x1F são inválidos porque JSON proíbe zeros à esquerda, um sinal de adição inicial e notação hexadecimal.
Use sequências de escape dentro de cadeias de caracteres
Use \" para aspas duplas, \\ para uma barra invertida, \n para uma nova linha e \t para uma tabulação dentro de uma cadeia JSON. Uma quebra de linha literal não pode aparecer dentro de uma cadeia JSON. Deixe JSON.stringify gerar sequências de escape a partir dos valores reais das cadeias de caracteres, para que aspas internas não invalidem a saída.
Uma sequência de escape Unicode consiste em uma barra invertida, a letra u e quatro dígitos hexadecimais para uma unidade de código UTF-16. Por exemplo, \u00e9 representa é. Um caractere fora desse intervalo pode precisar de duas dessas sequências; ele também pode ser escrito diretamente na cadeia. As aspas ao redor de um texto JSON no código-fonte JavaScript são uma camada separada das aspas dentro do próprio JSON.
Preserve identificadores e evite chaves duplicadas
Números JavaScript preservam todos os inteiros no intervalo seguro de -9007199254740991 até 9007199254740991. Fora desse intervalo, alguns inteiros permanecem exatos e outros são arredondados. Analisar '{"id":9007199254740993}' fornece um valor id de 9007199254740992. Armazene identificadores longos como cadeias de caracteres JSON quando seus dígitos exatos forem importantes.
Chaves devem ser únicas dentro de cada objeto JSON. O JSON.parse do JavaScript mantém a última ocorrência quando uma chave se repete: analisar '{"a":1,"a":2}' produz { a: 2 }. Não é possível recuperar propriedades distintas desse nome repetido.
Principais conclusões
- JSON é texto com seis tipos de valor, incluindo valores primitivos no nível superior.
- Chaves e cadeias de caracteres precisam de aspas duplas; comentários e vírgulas finais são inválidos.
- Números JSON não aceitam notação hexadecimal, sinais de adição iniciais nem zeros à esquerda.
- Sequências de escape representam caracteres especiais dentro de cadeias de caracteres.
- Use cadeias de caracteres para identificadores longos cujos dígitos exatos precisam ser preservados.
- Chaves de objeto repetidas são inseguras;
JSON.parsemantém o último valor.
5.2 Converter valores em texto JSON com JSON.stringify
JSON.stringify converte valores JavaScript compatíveis em texto JSON. Decida o que o texto deve preservar antes de converter um registro com métodos ou valores de coleções.
Escreva texto compacto ou indentado
const person = { name: "Amara", age: 34, tags: ["admin"] };
const text = JSON.stringify(person);
// '{"name":"Amara","age":34,"tags":["admin"]}'
O resultado é uma cadeia de caracteres, então typeof text é "string". Propriedades próprias enumeráveis com chaves de cadeia de caracteres são escritas na ordem de Object.keys. JSON.stringify(person, null, 2) adiciona quebras de linha e dois espaços de indentação por nível. O segundo argumento é null porque nenhum substituidor está sendo usado. A indentação numérica é limitada a 10 espaços; uma cadeia de caracteres usada para indentação é limitada aos seus primeiros 10 caracteres.
Preveja valores descartados e alterados
const data = {
a: undefined,
b: () => 1,
c: NaN,
d: [undefined, Infinity]
};
JSON.stringify(data); // '{"c":null,"d":[null,null]}'
Uma propriedade de objeto que contém undefined, uma função ou um símbolo é omitida. Em um vetor, esse valor se torna null, preservando a posição. NaN e Infinity tornam-se null em ambos os lugares. No nível superior, valores não suportados como undefined ou uma função fazem stringify retornar undefined, não texto JSON.
Um Date escreve sua cadeia ISO em UTC por meio de toJSON. Entradas comuns de Map e Set não são escritas, então qualquer uma das coleções se torna {}. Converta valores de Set em um vetor e entradas de Map em pares ou em um objeto com chaves de cadeia de caracteres antes de escrevê-los.
Uma referência circular e um BigInt comum como 10n causam um TypeError. Referências compartilhadas que não formam um ciclo podem ser serializadas, mas JSON não preservará sua identidade compartilhada.
Escolha dados com um substituidor
const user = { name: "Rae", email: "rae@example.com", password: "x9!k", age: 31 };
JSON.stringify(user, ["name", "email"]);
// '{"name":"Rae","email":"rae@example.com"}'
Um vetor substituidor seleciona nomes de propriedades. Uma função substituidora transforma valores à medida que são visitados, começando com toda a entrada sob a chave "":
JSON.stringify(user, (key, value) =>
key === "password" ? undefined : value
);
Retornar undefined omite uma propriedade de objeto, transforma uma posição de vetor em null ou causa um resultado geral undefined quando retornado para a raiz. Retorne o valor inalterado para os dados que você quer manter.
O método toJSON() de um objeto pode escolher sua representação. Para { celsius: 21, toJSON() { return { c: this.celsius }; } }, a conversão em texto escreve '{"c":21}'.
Não construa JSON juntando você mesmo cadeias de caracteres entre aspas: aspas internas ou novas linhas podem invalidar sua sintaxe. Também não converta novamente em texto um texto já serializado esperando uma representação de objeto. Converter '{"a":1}' em texto codifica uma cadeia de caracteres; analisar esse resultado uma vez retorna uma cadeia de caracteres, não um objeto.
Principais conclusões
JSON.stringifygeralmente retorna texto JSON; valores não suportados no nível superior podem retornarundefined.- Propriedades de objeto não suportadas desaparecem, enquanto itens de vetor não suportados se tornam
null. - Datas tornam-se cadeias de caracteres; Map e Set precisam de conversão explícita.
- Estruturas circulares e BigInts comuns lançam
TypeError. - Substituidores e
toJSONcontrolam a representação escrita. - Converter texto JSON novamente codifica uma cadeia de caracteres, não o objeto contido nela.
5.3 Converter texto JSON em valores com JSON.parse
JSON.parse lê texto JSON e retorna o valor que ele descreve. A análise sintática verifica a sintaxe do texto; verificar se o resultado é adequado ao seu programa é uma tarefa separada.
Leia o valor e depois examine seus campos
const data = JSON.parse('{"city":"Lima","tempC":19.5}');
data.tempC + 1; // 20.5
As aspas simples externas delimitam uma cadeia de caracteres JavaScript. As aspas duplas dentro dela pertencem ao JSON. A análise sintática cria um objeto comum com uma propriedade numérica tempC. Um texto que descreve um vetor produz um vetor; textos JSON primitivos produzem seus valores primitivos correspondentes.
Dados que já são um objeto não precisam de uma etapa de análise sintática. JSON.parse({ a: 1 }) primeiro converte esse argumento em "[object Object]" e depois lança um SyntaxError. JSON.parse(undefined) também falha porque "undefined" não é texto JSON válido.
Trate texto inválido
function safeParse(text, fallback) {
try {
return JSON.parse(text);
} catch (error) {
return fallback;
}
}
safeParse("{ok:true}", null); // null
Uma entrada malformada, incluindo uma cadeia de caracteres vazia, cadeias JSON entre aspas simples, chaves sem aspas e vírgulas finais, lança um SyntaxError. Capturar essa falha dá ao programa uma alternativa de contingência definida, em vez de interrompê-lo. Um null analisado com sucesso também é possível, então escolha como quem chama distinguirá uma alternativa de contingência de dados válidos quando essa diferença importar.
Restaure valores selecionados com uma função restauradora
Uma data armazenada como texto retorna como uma cadeia de caracteres. Um vetor de pares chave-valor permanece um vetor até que new Map(pairs) o transforme em um Map. Funções omitidas durante a escrita não podem ser recuperadas do texto restante.
const text = '{"title":"Dentist","due":"2026-03-01T09:00:00.000Z"}';
const event = JSON.parse(text, (key, value) =>
key === "due" ? new Date(value) : value
);
A função restauradora visita valores internos antes de seus contêineres, terminando com o resultado inteiro sob a chave "". Retornar um valor substitui o valor atual. Retornar undefined remove essa propriedade; retorná-lo para a raiz faz todo o resultado da análise ser undefined. Esquecer return value para outras chaves pode, portanto, apagar os dados que você queria manter.
Verifique a estrutura e planeje uma conversão de ida e volta
JSON válido ainda pode ter os tipos errados. Analisar '{"temp":"19"}' deixa uma cadeia de caracteres, então data.temp + 1 concatenaria para "191". Verifique campos e tipos obrigatórios, como typeof data?.temp === "number", antes de calcular. Converta com Number apenas quando o formato pretendido permitir uma cadeia numérica; o encadeamento opcional e ?? podem tratar campos que podem estar ausentes.
Para const settings = { theme: "dark", volume: 0.8, recent: ["a.txt"] };, a conversão em texto produz 48 caracteres de texto JSON. A análise sintática restaura os mesmos dados dos campos, mas loaded === settings é falso porque ela cria novos objetos. Um Date retorna como uma cadeia de caracteres, uma propriedade de objeto com valor undefined desaparece e um Set não convertido retorna como {}. Converta valores especiais antes de escrever e restaure seus tipos pretendidos após a leitura.
Principais conclusões
JSON.parselê texto e lançaSyntaxErrorpara JSON malformado.- Uma análise sintática bem-sucedida não verifica os campos obrigatórios nem seus tipos.
- Uma função restauradora visita primeiro os valores filhos e deve retornar os valores que você quer manter.
- Conversões de ida e volta por JSON criam novos objetos e preservam apenas dados representáveis.
- Restaure explicitamente os tipos de coleções e datas após a análise sintática.
Exercícios resolvidos de Objetos e JSON
1Acompanhar um registro de remessa
16 passos
- 1IntroduçãoConstrua um registro que você possa examinar
Uma remessa combina um ID, um destino e registros de pacotes. Você vai construí-la, examinar seus campos e acompanhar dados compartilhados e copiados. Dois nomes podem guardar uma referência ao mesmo registro, e uma cópia rasa ainda compartilha os níveis aninhados, então uma atualização pode alcançar dados que você pretendia manter separados.
Os exemplos da remessa continuam entre os slides, a menos que uma etapa crie explicitamente um objeto separado.
- 2ExemploCrie a remessa
const shipment = { id: "s12", destination: "Porto", delayMin: 0 };O literal cria três propriedades. O atraso é medido em minutos e pode ser zero.
shipment.destinationlê"Porto". Const permite atualizações das propriedades. - 3ExemploEscolha um campo durante a execução do programa
const field = "destination"; shipment[field] = "Braga"; shipment.checked = true;O acesso por colchetes avalia field e atualiza a propriedade de destino. A atribuição também adiciona checked porque ela não existia antes. A remessa continua com a mesma identidade; nenhuma das operações substitui o objeto externo. Escrever
shipment.fieldcriaria uma propriedade separada literalmente chamada"field". - 4DesafioLeia um nome computado
O que
shipment[field]lê agora, e a remessa tem uma propriedade própria field?---reveal---
Ela lê
"Braga". A variável field contém a chave"destination", então tanto a atualização quanto a leitura acessam essa propriedade.Object.hasOwn(shipment, "field")é false porque nenhuma propriedade literal field foi criada. Uma variável usada para escolher uma propriedade não se torna parte do registro. - 5ExplicaçãoVerifique zero sem perdê-lo
shipment.delayMiné zero, então uma condição que testa se o valor é avaliado como verdadeiro ignora seu corpo. A propriedade continua existindo.Object.hasOwn(shipment, "delayMin")retorna true. Use uma verificação de propriedade própria para campos armazenados; o operador in também inclui propriedades herdadas. - 6ExemploLeia os pares chave-valor
const pairs = Object.entries(shipment); const count = Object.keys(shipment).length;Agora há quatro campos próprios enumeráveis com chaves de cadeia de caracteres, incluindo checked. Entries fornece um par
[key, value]para cada um. Você pode usar o laçofor (const [key, value] of pairs)para examinar ambas as partes. Um laço for...of direto sobre o objeto comum shipment lançaria um erro porque esse objeto não é iterável. - 7DesafioSepare existência de valor
Suponha que
shipment.note = undefined;seja adicionado. O queshipment.noteeObject.hasOwn(shipment, "note")retornam?---reveal---
Eles retornam undefined e true. A atribuição cria a propriedade mesmo que seu valor seja undefined. Excluir a propriedade mudaria o resultado da verificação de existência para false, enquanto uma leitura posterior ainda produziria undefined. O valor sozinho não consegue distinguir essas duas situações.
- 8AnalogiaAcompanhe dois caminhos até um registro
Uma referência funciona como um caminho até um registro: copiar o caminho oferece outra maneira de chegar ao mesmo destino. Isso não constrói um segundo registro.
const alias = shipment; alias.checked = false;shipment.checkedagora também é false. Ambos os nomes de variáveis acessam um objeto, entãoalias === shipmenté true. Referências iguais explicam a atualização compartilhada; nenhuma etapa de sincronização foi executada entre duas cópias. - 9ExemploAdicione dados que uma cópia superficial compartilhará
shipment.packages = [{ massG: 450 }, { massG: 700 }]; const shallow = { ...shipment }; shallow.destination = "Faro"; shallow.packages[0].massG = 500;O novo registro externo tem seu próprio destino, então
shipment.destinationcontinua sendo Braga. Seu valor packages é a mesma referência de vetor de antes. Seguir esse caminho compartilhado também altera para 500 a massa do primeiro pacote na remessa original. - 10ExemploFaça uma cópia profunda de dados compatíveis
const deep = structuredClone(shipment); deep.packages[0].massG = 600;O primeiro pacote original permanece com 500 g porque a cópia profunda tem seu próprio vetor aninhado e seus próprios objetos de pacote. Esse registro contém apenas dados compatíveis. Se contivesse uma propriedade cujo valor fosse uma função, structuredClone lançaria DataCloneError em vez de descartar silenciosamente esse método.
- 11DesafioPreveja o alcance do congelamento
Execute estas instruções. A atribuição aninhada lança um erro e qual é a segunda massa depois dela?
Object.freeze(shipment); shipment.packages[1].massG = 750;---reveal---
Ela é bem-sucedida e define a massa como 750. Congelar shipment protege suas propriedades próprias, mas não o vetor referenciado nem seus registros. Reatribuir
shipment.destinationem modo estrito lançaria TypeError; essa atribuição aninhada acessa outro objeto, que não está congelado. - 12ExemploCalcule o total atual
const totalG = shipment.packages.reduce( (sum, pack) => sum + pack.massG, 0 );Após as atualizações anteriores, a remessa original contém massas de 500 e 750 g. Reduce começa em zero, soma 500 e depois 750, produzindo 1250. O total é calculado a partir dos pacotes atuais. Se suas massas mudarem depois, execute o cálculo novamente; esse número armazenado não se recalcula sozinho.
- 13DicaProteja um caminho opcional
const contactName = shipment.contact?.name ?? "Unassigned";Não há propriedade contact no registro, então o encadeamento opcional resulta em undefined e a alternativa de contingência fornece
"Unassigned". Esse caminho pode estar ausente. Mantenha os campos obrigatórios visíveis para validação em vez de usar valores padrão silenciosamente para todos os erros. A alternativa para valores nulos ou indefinidos também preserva um nome intencionalmente vazio, diferentemente de uma alternativa com OU lógico. - 14DesafioMantenha um zero válido
O que
shipment.delayMin ?? 10eshipment.delayMin || 10retornam?---reveal---
O primeiro retorna 0; o segundo retorna 10. A coalescência nula substitui apenas null ou undefined, enquanto o OU lógico substitui todo valor avaliado como falso. Essa remessa tem um atraso registrado de zero minuto, então tratá-lo como ausente introduziria um atraso que os dados armazenados nunca informaram.
- 15DesafioCombine uma cópia com uma atualização opcional
Um novo registro é criado com
const next = { ...shipment };e, em seguida,next.packages[0].massG = 520;. O que acontece com a primeira massa de shipment, e next é o mesmo objeto externo?---reveal---
A massa original se torna 520 porque o vetor aninhado é compartilhado.
next === shipmenté false porque o espalhamento criou um novo objeto externo. Copiar o registro externo separa as atribuições às suas próprias propriedades, mas não torna independente todo um caminho aninhado. - 16RecapitulaçãoEscolha a verificação adequada à tarefa
Escolha uma propriedade por chave literal ou computada e distinga a existência do fato de um valor ser avaliado como verdadeiro. Antes de uma atualização, acompanhe se seu caminho chega a dados compartilhados.
Copie níveis aninhados que precisam ser independentes. Recalcule totais derivados após suas entradas mudarem.
2Manter uma ação conectada ao seu objeto
12 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoAcompanhe uma ação ao ser passada adiante
- 2ExemploCrie e chame uma ação
- 3DesafioLeia a ação sem executá-la
- 4ExemploEmpreste a função comum
- 5DesafioDesvincule o método emprestado
- 6Ideia-chaveColoque uma função de seta dentro do método
- 7ExemploEnvolva a chamada necessária
- 8ExemploVincule uma função de retorno uma vez
- 9DesafioEscolha entre execução imediata ou posterior
- 10DicaDê prioridade a uma vinculação existente
- 11DesafioAcompanhe um método vinculado por outro objeto
- 12RecapitulaçãoLeia a forma da chamada
3Extrair opções e construir um registro atualizado
14 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoLeia a sintaxe compacta em pequenas etapas
- 2ExemploSelecione e renomeie campos
- 3ExemploAcesse um padrão aninhado
- 4DesafioLeia um campo aninhado renomeado
- 5DesafioMantenha null distinto de um valor ausente
- 6ExemploExtraia um intervalo retornado
- 7ExemploColete o restante em seu próprio vetor
- 8DesafioTroque valores antes de usá-los
- 9ExemploMescle valores padrão com substituições
- 10ExemploCopie o nível aninhado que muda
- 11ConexãoRemova um campo do novo registro
- 12DesafioEscolha uma atualização independente
- 13DesafioConecte padrões de pares chave-valor ao espalhamento
- 14RecapitulaçãoIdentifique a função antes de acompanhar os valores
4Acompanhar contagens e pertinência de valores únicos
11 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoEscolha o que a coleção deve manter
- 2ExemploCrie contagens com métodos de Map
- 3DicaMantenha entradas separadas de propriedades
- 4DesafioMantenha distintos os tipos de chave
- 5ExemploReutilize uma chave que é objeto
- 6ExemploColete rótulos únicos
- 7DesafioDecida se registros são duplicatas
- 8ExemploEncontre os rótulos compartilhados e ausentes
- 9Ideia-chaveMude a pergunta sobre pertinência
- 10DesafioRelacione contagens à pertinência
- 11RecapitulaçãoEscolha a estrutura adequada à operação
5Escrever, ler e verificar dados JSON
14 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoPlaneje as duas direções da conversão
- 2ExplicaçãoLeia texto como texto
- 3DesafioCorrija um problema de sintaxe
- 4ExemploExamine as configurações em uso
- 5ExemploConverta a coleção antes de escrever
- 6DicaDeixe o serializador aplicar sequências de escape
- 7DesafioPreveja um item de vetor não suportado
- 8ExemploAnalise e restaure as operações de pertinência
- 9ExemploTrate texto malformado de forma planejada
- 10DesafioVerifique um valor válido, mas inadequado
- 11ExplicaçãoRestaure um campo com uma função restauradora
- 12DesafioPreserve a distinção entre chaves de Map
- 13ConexãoMantenha clonagem e troca de dados separadas
- 14RecapitulaçãoVerifique sintaxe, estrutura e representação
Questões de Objetos e JSON
Conjunto 1: Aplicar padrões e preservar objetos receptores10 Questões de Prática
Questão 1 de 10
Qual é o valor final de loaded?
const loaded = JSON.parse('{"count":4,"tag":"a"}', (key, value) => {
if (key === "count") return value * 2;
});
Mostrar respostaOcultar resposta
"", remove o resultado inteiro. Manter apenas { count: 8 } deixaria de considerar que a função restauradora também processa a raiz.Questão 2 de 10
O que acontece quando esse texto é analisado?
JSON.parse('{"mode":"fast","mode":"slow"}');
Mostrar respostaOcultar resposta
"slow". Nomes únicos são recomendados, mas esse nome repetido não faz JSON.parse lançar SyntaxError.Questão 3 de 10
O que trip.host?.name ?? "Guest" retorna?
const trip = { host: null };
Mostrar respostaOcultar resposta
"Guest". Retornar undefined considera o primeiro operador, mas deixa de fora a alternativa de contingência.Questão 4 de 10
Quais são os valores finais de a.level e a === b?
const a = { level: 2 };
const b = a;
b.level = 5;
Mostrar respostaOcultar resposta
a a b copia a referência ao objeto existente. Atualizar b.level altera, portanto, o objeto também acessado por a, então o nível é 5 e a identidade é compartilhada. Tratar essa atribuição como uma cópia do registro deixaria incorretamente o nível original em 2.Questão 5 de 10
Quais são os valores de source.mode e source.layout.width depois disso?
const source = { mode: "day", layout: { width: 40 } };
const copy = { ...source };
copy.mode = "night";
copy.layout.width = 60;
Mostrar respostaOcultar resposta
mode não altera source.mode. Ambos os registros ainda contêm a mesma referência layout, fazendo a largura aninhada ser 60 em ambos. Manter a largura em 40 exigiria uma cópia aninhada separada, que esse código não cria.Questão 6 de 10
Qual função pode ser passada a map para que cada chamada atualize tally?
const tally = { n: 0, tick() { return ++this.n; } };
const result = ["x", "y"].map(/* callback */);
Mostrar respostaOcultar resposta
tally como objeto receptor cada vez que map a chama. Passar tally.tick desvincula o método comum e perde esse objeto receptor. Adicionar parênteses fora de uma função envoltória o executa imediatamente e passa um número, enquanto retornar tally.tick apenas retorna a função sem executá-la.Questão 7 de 10
Este código é executado no nível superior de um módulo. O que acontece quando card.read() é chamado?
const card = { title: "Basin", read: () => this.title };
Mostrar respostaOcultar resposta
this.title lança, portanto, TypeError. Um literal de objeto não fornece um novo this a uma função de seta, então a chamada com aparência de método não pode fazê-la retornar "Basin"; um método comum usaria card como objeto receptor.Questão 8 de 10
Após next.panel.width = 90, quais são os valores de next.mode e base.panel.width?
const base = { mode: "wide", panel: { width: 50 } };
const next = { mode: "small", ...base, panel: { ...base.panel } };
Mostrar respostaOcultar resposta
"wide". A propriedade panel final cria um objeto aninhado separado, então alterar sua largura deixa a original em 50. Prever 90 para a original deixaria de considerar esse segundo espalhamento, enquanto "small" ignoraria a ordem de sobrescrita.Questão 9 de 10
Qual valor size recebe?
const { size = 6 } = {};
Mostrar respostaOcultar resposta
Questão 10 de 10
Qual vetor essa expressão produz?
[...new Set(["red", "blue", "red", "green", "blue"])];
Mostrar respostaOcultar resposta
Conjunto 2: Transformar coleções e recuperar dados10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Qual vetor é retornado neste módulo?
function scale(n) { return this.factor * n; }
const twice = scale.bind({ factor: 2 });
const obj = { factor: 9, twice };
[obj.twice(3), twice.call({ factor: 5 }, 4)];
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
O que é retornado?
function combine(first, ...others) {
return [first, others.length];
}
combine(...[7, 3, 8, 2]);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Qual objeto a expressão cria?
Object.fromEntries(
Object.entries({ north: 3, south: 5 })
.map(([key, value]) => [key, value + 2])
);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
O que options.limit ?? 12 retorna?
const options = { limit: 0 };
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
O que add deve retornar para que basket.add("pear").add("fig") use o mesmo basket duas vezes?
const basket = {
items: [],
add(item) { this.items.push(item); /* return here */ }
};
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Quais são os valores de items[0].done, next[1] === items[1] e next === items?
const items = [{ id: 4, done: false }, { id: 9, done: false }];
const next = items.map(item =>
item.id === 4 ? { ...item, done: true } : item
);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
Por que lookup.get({ code: 8 }) é undefined?
const key = { code: 8 };
const lookup = new Map([[key, "ready"]]);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Quais são os tamanhos de a.difference(b) e a.symmetricDifference(b)?
const a = new Set([2, 4, 6]);
const b = new Set([4, 8]);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Que texto isso produz?
JSON.stringify({ label: "Arc", count: 3 }, ["label"]);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Este módulo é executado sem uma função restauradora. Quais são os valores de typeof loaded.due e loaded === original?
const original = { due: new Date("2026-07-12T00:00:00.000Z") };
const loaded = JSON.parse(JSON.stringify(original));
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 3: Ler registros e acompanhar valores10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Quais são os valores de m.size e m.get(2)?
const m = new Map([[2, "number"], ["2", "text"]]);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Qual valor third recebe?
const [, , third] = [4, 9, 12, 18];
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
O que sensor[field] retorna?
const sensor = { tempC: 16, field: "room" };
const field = "tempC";
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
O que Object.hasOwn(record, "enabled") retorna?
const record = { enabled: false };
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
Quais são os valores de record.region e record.key?
const key = "region";
const record = { [key]: "east" };
record[key] = "west";
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Qual é o valor de meter.value após essa chamada?
const meter = {
value: 7,
add() { this.value += 3; }
};
meter.add();
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
O que right.read() retorna?
const left = { name: "Ivo", read() { return this.name; } };
const right = { name: "Nia", read: left.read };
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Quais são os valores de title e score após a desestruturação?
const { name: title, score = 8 } = { name: "Reef", score: null };
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Que texto é retornado?
JSON.stringify({
note: undefined,
values: [undefined, NaN],
ok: false
});
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 4: Diagnosticar atualizações e chamadas10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Qual é o valor de typeof box.open?
const box = { open() { return "opened"; } };
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Quais são os valores de base.inner.n, clone.inner.n e copy.inner.n ao final?
const base = { inner: { n: 2 } };
const copy = { ...base };
const clone = structuredClone(base);
Object.freeze(base);
copy.inner.n = 7;
clone.inner.n = 9;
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Qual vetor Object.keys(data) retorna?
const data = { z: 1, "10": 2, "02": 3, "2": 4, a: 5 };
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
Quanto vale totalG, e alterar heavy.massG também altera load.items[1].massG?
const load = { items: [
{ massG: 120, qty: 2 },
{ massG: 300, qty: 1 }
] };
const heavy = load.items.find(x => x.massG > 200);
const totalG = load.items.reduce((s, x) => s + x.massG * x.qty, 0);
heavy.massG = 350;
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
O que b.labels() retorna neste módulo?
const a = {
prefix: "A",
names: ["oak"],
labels() { return this.names.map(n => this.prefix + n); }
};
const b = { prefix: "B", names: ["elm"], labels: a.labels };
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
O que acontece quando read() e read({ prefs: null }) são chamados separadamente?
function read({ prefs: { theme = "light" } = {} } = {}) {
return theme;
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
Qual é o valor de tail?
const [head, ...tail] = [6, 8, 11];
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Quais são os valores de m.size e [...m.keys()]?
const m = new Map([["p", 1], ["q", 2]]);
m.set("p", 4);
m["r"] = 5;
m.delete("q");
m.set("q", 6);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
JSON.parse('{"depthM":+7}') falha?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Quais são os valores de result.count e result.total?
const result = JSON.parse('{"count":"6","total":12}',
(key, value) => key === "count" ? Number(value) : value
);
result.total += result.count;
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 5: Combinar escolhas de dados e regras de conversão10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Após publicCopy.profile.name = "New", qual é o valor de source.profile.name, e source ainda possui a propriedade própria secret?
const source = { secret: "s", profile: { name: "Old" } };
const { secret, ...publicCopy } = source;
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Qual é o valor final de counts.get("moss")?
const counts = new Map();
for (const word of ["moss", "fern", "moss", "moss"]) {
counts.set(word, (counts.get(word) ?? 0) + 1);
}
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Quais são os valores de records.size e ids.size?
const x = { id: 7 };
const records = new Set([x, x, { id: 7 }]);
const ids = new Set([...records].map(r => r.id));
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
Qual é o valor de typeof JSON.parse(text)?
const text = JSON.stringify('{"x":3}');
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
Qual é o valor de Object.hasOwn(record, "old") após estas instruções?
const record = { old: undefined };
delete record.old;
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Quais são os valores de a === b, a.left === a.right e b.left === b.right?
const shared = { n: 1 };
const a = { left: shared, right: shared };
const b = JSON.parse(JSON.stringify(a));
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
O que saved() retorna?
const maker = {
n: 5,
make() { return () => this.n; }
};
const other = { n: 8, make: maker.make };
const saved = other.make().bind({ n: 12 });
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
O que fixed.apply({ offset: 30 }, [4]) retorna?
function add(a, b) { return this.offset + a + b; }
const fixed = add.bind({ offset: 2 }, 7);
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Quais são os valores de a, b e rest?
let a = 3, b = 8;
[a, b] = [b, a];
const [, ...rest] = [a, b, 13];
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
"3", com os valores "n" e "s". Qual par de conversões as preserva por meio de JSON?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Travou em uma questão sua? Ajuda com Tarefas
Termos-Chave
A
Aplicação parcial
multiply.bind(null, 4) cria uma função que multiplica seu próximo argumento por quatro.Argumento de indentação
Argumento substituidor
Atualização imutável
C
Cadeia de caracteres JSON
Chamada simples em modo estrito
f e chamar f() em um módulo pode falhar quando ele tenta ler this.name.Chave de índice de vetor
"3" vem antes de "12" em Object.keys; "03" permanece entre as chaves comuns de cadeia de caracteres.Coalescência nula
settings.volume ?? 1 mantém um volume explícito de zero, enquanto settings.volume || 1 o substitui.Coleção WeakMap
Coleção WeakSet
Conjunto (Set)
"ready" duas vezes mantém um valor, enquanto adicionar dois registros separados com dados iguais mantém ambos.Conversão de ida e volta
Cópia profunda
structuredClone com dados compatíveis, editar um campo aninhado copiado deixa o campo original inalterado.Cópia superficial
D
Dados aninhados
report.readings[0].tempC lê uma lista, seu primeiro registro e depois um campo de temperatura.Desestruturação de objetos
const { city, tempC } = reading; cria duas variáveis locais a partir de um registro meteorológico.Desestruturação de vetores
const [low, high] = bounds; depende de bounds colocar o menor valor antes do maior.Diferença
active.difference(blocked) mantém valores ativos que não aparecem no Set de bloqueados.Diferença simétrica
E
Elemento rest de vetor
const [leader, ...others] = names; separa o primeiro nome de um vetor com os nomes restantes.Encadeamento de métodos
list.add("a").add("b") funciona quando a primeira chamada retorna um objeto com o próximo método add.Encadeamento opcional
record.owner?.name permite que owner esteja ausente sem tentar ler um nome de undefined.Entrada de Map
stock.set("tea", 4) altera uma entrada; stock["tea"] = 4 altera uma propriedade comum.Erro de sintaxe (SyntaxError)
JSON.parse.Espalhamento de iteráveis
Math.max(...measurements) fornece cada item do vetor como um argumento separado para a função.Espalhamento de objetos
{ ...base, active: true } copia base e depois fornece o valor final para active.Existência de propriedade
count: 0 ainda tem uma propriedade count; testar esse valor como condição não detecta sua presença.F
Função envoltória de seta
() => counter.tick() para map faz cada função de retorno chamar tick por meio do objeto counter.Função restauradora
JSON.parse que transforma valores após seus filhos, usando seus valores de retorno para substituí-los ou removê-los.Função structuredClone
I
Identidade do objeto
id: 9 são considerados diferentes por === apesar dos dados iguais.Inteiro seguro
Interseção
Iterável
J
JSON
{"ready":true} descreve um registro, enquanto true sozinho também é um texto JSON completo e válido.L
Literal de objeto
const reading = { tempC: 22 }; cria um registro que contém uma medição de temperatura.M
Map
"5" permanecem entradas distintas quando armazenadas no mesmo Map.Método
tracker.advance() executa a ação de tracker, enquanto ler tracker.advance retorna uma função.Método apply
format.apply(reading, ["m", 2]) fornece o mesmo objeto receptor e os mesmos valores que format.call(reading, "m", 2).Método bind
const next = meter.step.bind(meter); cria uma função de retorno que mantém meter como objeto receptor.Método call
format.call(reading, "m", 2) fornece a format o objeto receptor reading e dois argumentos separados.Método desvinculado
const read = sensor.read; mantém a função, mas read() não fornece sensor como objeto receptor.Método emprestado
b.read = a.read permite que b.read() use os dados de b quando a função lê por meio de this.Método JSON.parse
JSON.parse lê texto JSON e retorna o valor JavaScript representado por ele, lançando um SyntaxError quando o texto está malformado.Método JSON.stringify
JSON.stringify serializa valores JavaScript suportados em texto JSON, podendo selecionar dados e adicionar indentação para leitura.JSON.stringify(settings, null, 2) escreve uma forma mais legível sem alterar as configurações representadas.Método Map.groupBy
Map.groupBy é um método mais recente que agrupa itens iteráveis em vetores dentro de um Map, preservando o tipo e a identidade das chaves de grupo.Método Object.freeze
Object.freeze impede adições, exclusões e alterações nas propriedades próprias de um objeto, mas não congela objetos aninhados.Método Object.fromEntries
Object.fromEntries cria um objeto a partir de pares chave-valor, sendo útil após uma transformação de pares ou a partir de um Map compatível.Método Object.groupBy
Object.groupBy é um método mais recente que agrupa itens iteráveis em vetores sob chaves selecionadas por uma função de retorno, em um objeto sem protótipo.Método toJSON
N
Nome de propriedade computado
const code = "es";, { [code]: "Hola" } cria uma propriedade chamada "es".Notação de colchetes
const field = "heightM";, person[field] seleciona a medida de altura da pessoa.Notação de ponto
profile.name sempre seleciona a propriedade chamada "name", mesmo que exista uma variável chamada name.O
Objeto de opções
{ color, size } permite que quem a chama indique o significado de cada configuração sem depender da ordem das posições.Objeto receptor
account.describe(), account é o objeto receptor que o método usa para ler seus campos.Ordem de inserção
P
Padrão aninhado
const { owner: { name } } = item; precisa de um objeto owner e declara apenas name.Padrão de renomeação
const { title: label } = page; cria label sem declarar uma variável chamada title.Palavra-chave this
Par chave-valor
Object.entries({ lake: 5 }) produz [["lake", 5]], pronto para um laço sobre chaves e valores.Parâmetro rest
function total(...values) pode usar reduce em values mesmo quando a chamada não fornece argumentos.Posição ignorada
const [, second] = colors; ignora a primeira cor e nomeia apenas o próximo valor fornecido.Propriedade
active em { active: false } existe mesmo que seu valor seja o booleano false.Propriedade abreviada
city, o literal { city } cria o mesmo campo que { city: city }.Propriedade globalThis
Propriedade própria
Object.hasOwn({}, "toString") é false, embora "toString" in {} seja true.R
Referência
const backup = record; oferece outra forma de acessar record sem copiar seus campos.Referência circular
record.self = record faz a chamada comum de JSON.stringify lançar um TypeError para esse registro.S
Sequência de escape
Serialização
Sintaxe abreviada de método
reset() { this.n = 0; } define uma ação sem dois-pontos separados e sem a palavra-chave function.Sintaxe rest de objetos
const { password, ...publicRecord } = user; deixa user intacto enquanto exclui password da cópia.Subconjunto
T
Teste de pertinência
map.has(key) pode encontrar uma entrada existente mesmo quando map.get(key) retorna undefined.this léxico
U
União
V
Valor derivado
Valor padrão na desestruturação
const { count = 2 } = { count: null };, o null explícito permanece apesar do valor padrão.Verificação da estrutura dos dados
Sobre esta aula
Crie seus próprios Materiais de Estudo
Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.