Objetos: criando, acessando e modificando propriedades
1. Fundamentos da Criação de Objetos
Objetos em JavaScript são coleções dinâmicas de pares chave-valor. A forma mais comum e recomendada de criá-los é através da sintaxe literal:
const usuario = {
nome: "Maria",
idade: 28,
email: "maria@exemplo.com"
};
Boas práticas de nomenclatura incluem usar camelCase para chaves e evitar caracteres especiais. Embora seja possível usar new Object(), a sintaxe literal é preferida por ser mais concisa e legível:
// Evite
const config = new Object();
config.url = "https://api.exemplo.com";
config.timeout = 5000;
// Prefira
const config = { url: "https://api.exemplo.com", timeout: 5000 };
Objetos aninhados permitem criar estruturas complexas, como dados de usuário ou configurações de API:
const usuarioCompleto = {
nome: "João",
endereco: {
rua: "Av. Paulista",
numero: 1000,
cidade: "São Paulo"
},
preferencias: {
tema: "escuro",
notificacoes: { email: true, push: false }
}
};
2. Acessando Propriedades de Forma Eficiente
A notação de ponto (obj.prop) é a mais simples e legível, mas possui limitações com nomes dinâmicos ou chaves com caracteres especiais:
const carro = { marca: "Toyota", "ano-fabricacao": 2022 };
console.log(carro.marca); // "Toyota"
// console.log(carro.ano-fabricacao); // Erro! Hífen não permitido
console.log(carro["ano-fabricacao"]); // 2022
A notação de colchetes permite acessar propriedades com variáveis e strings especiais:
const chave = "modelo";
carro[chave] = "Corolla";
const propriedades = ["marca", "modelo", "ano-fabricacao"];
propriedades.forEach(prop => console.log(carro[prop]));
Para acessar propriedades aninhadas com segurança, utilize o encadeamento opcional (?.):
const usuario = { perfil: { nome: "Ana" } };
console.log(usuario.perfil?.nome); // "Ana"
console.log(usuario.contato?.telefone); // undefined (sem erro)
console.log(usuario?.endereco?.cep); // undefined
3. Modificando Propriedades Existentes
A atualização direta é feita por reatribuição simples:
const produto = { nome: "Notebook", preco: 3500 };
produto.preco = 3200; // Atualização direta
produto["em-estoque"] = true;
Ao modificar propriedades aninhadas, tenha cuidado com mutação acidental:
const configSistema = {
banco: { host: "localhost", porta: 5432 },
cache: { ativo: true, tempo: 3600 }
};
// Modificação segura de propriedade aninhada
configSistema.banco.porta = 5433;
O método Object.assign() é útil para atualizações parciais:
const defaults = { tema: "claro", idioma: "pt-BR", timeout: 3000 };
const userConfig = { tema: "escuro" };
const configFinal = Object.assign({}, defaults, userConfig);
console.log(configFinal); // { tema: "escuro", idioma: "pt-BR", timeout: 3000 }
4. Adicionando e Removendo Propriedades
Adicionar novas chaves dinamicamente é simples:
const pedido = { id: 123, itens: ["camiseta"] };
pedido.status = "pendente";
pedido["data-criacao"] = new Date().toISOString();
Para remover propriedades, utilize o operador delete:
const cliente = { nome: "Carlos", cpf: "123.456.789-00", senha: "secreta" };
delete cliente.senha;
console.log(cliente); // { nome: "Carlos", cpf: "123.456.789-00" }
Boas práticas: evite deletar propriedades em objetos frequentemente acessados (como em loops), pois isso pode degradar a performance. Prefira criar novos objetos sem as propriedades indesejadas.
5. Propriedades Computadas e Dinâmicas
Propriedades computadas permitem criar chaves dinâmicas na declaração:
const prefixo = "usuario_";
const id = 42;
const registro = {
[prefixo + id]: "João Silva",
[`timestamp_${Date.now()}`]: new Date().toISOString()
};
Em tempo de execução, é possível atualizar propriedades com nomes gerados dinamicamente:
function atualizarConfig(chave, valor) {
const config = { tema: "claro" };
config[chave] = valor;
return config;
}
console.log(atualizarConfig("idioma", "en")); // { tema: "claro", idioma: "en" }
Exemplo prático em React: mapeando dados de formulário para objeto:
function handleFormSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const dados = {};
for (let [chave, valor] of formData.entries()) {
dados[chave] = valor;
}
console.log(dados); // { nome: "Maria", email: "maria@exemplo.com" }
}
6. Imutabilidade e Cópia de Objetos
Objetos são passados por referência, não por valor:
const original = { valor: 10 };
const copiaReferencia = original;
copiaReferencia.valor = 20;
console.log(original.valor); // 20 - foi modificado!
Para cópia rasa, use spread operator ou Object.assign():
const original = { a: 1, b: { c: 2 } };
const copiaRasa = { ...original };
copiaRasa.a = 100;
copiaRasa.b.c = 200;
console.log(original.b.c); // 200 - objetos aninhados ainda compartilham referência
Para cópia profunda, utilize JSON.parse(JSON.stringify(obj)) ou bibliotecas como lodash:
const profundo = JSON.parse(JSON.stringify(original));
profundo.b.c = 999;
console.log(original.b.c); // 200 - inalterado
// Com lodash: const copiaProfunda = _.cloneDeep(original);
7. Iterando e Listando Propriedades
Diferentes métodos para iterar sobre propriedades:
const dados = { nome: "Ana", idade: 30, cidade: "Rio" };
// for...in (inclui propriedades do protótipo)
for (let chave in dados) {
console.log(`${chave}: ${dados[chave]}`);
}
// Object.keys() - apenas próprias
Object.keys(dados).forEach(chave => console.log(chave));
// Object.values()
Object.values(dados).forEach(valor => console.log(valor));
// Object.entries() - útil para React
Object.entries(dados).forEach(([chave, valor]) => {
console.log(`${chave}: ${valor}`);
});
Verificando existência de propriedades:
const obj = { nome: "Pedro" };
console.log(obj.hasOwnProperty("nome")); // true
console.log("nome" in obj); // true
console.log(obj.hasOwnProperty("toString")); // false (herdado)
console.log("toString" in obj); // true (herdado)
Exemplo React: renderizando listas com .map() e .entries():
function TabelaUsuario({ usuario }) {
return (
<table>
<tbody>
{Object.entries(usuario).map(([chave, valor]) => (
<tr key={chave}>
<td>{chave}</td>
<td>{String(valor)}</td>
</tr>
))}
</tbody>
</table>
);
}
8. Boas Práticas em Projetos Node.js e React
Desestruturação de objetos em parâmetros de funções (especialmente em componentes React):
// Em vez de:
function Saudacao(props) {
return <h1>Olá, {props.nome}</h1>;
}
// Prefira:
function Saudacao({ nome, idade }) {
return <h1>Olá, {nome} - {idade} anos</h1>;
}
Propriedades padrão com valores fallback:
function ConfigCard({ tema = "claro", idioma = "pt-BR", timeout = 3000 }) {
return (
<div className={`card card-${tema}`}>
<p>Idioma: {idioma}</p>
<p>Timeout: {timeout}ms</p>
</div>
);
}
Cuidados com mutação em estado React (sempre use imutabilidade):
// ERRADO - muta o estado diretamente
function atualizarUsuario(usuario, novaCidade) {
usuario.cidade = novaCidade; // ❌ Muta o objeto original
return usuario;
}
// CORRETO - cria novo objeto
function atualizarUsuario(usuario, novaCidade) {
return { ...usuario, cidade: novaCidade }; // ✅ Imutável
}
// Exemplo com estado React
const [usuario, setUsuario] = useState({ nome: "João", cidade: "SP" });
function handleCidadeChange(novaCidade) {
setUsuario(prev => ({ ...prev, cidade: novaCidade }));
}
Referências
- MDN Web Docs: Trabalhando com Objetos — Guia completo sobre criação, acesso e modificação de objetos em JavaScript.
- JavaScript.info: Objects — Tutorial detalhado com exemplos práticos sobre objetos no JavaScript moderno.
- React Documentation: State and Lifecycle — Documentação oficial sobre gerenciamento de estado e imutabilidade em React.
- Node.js Documentation: Objects — Introdução ao uso de objetos no contexto Node.js, incluindo boas práticas.
- W3Schools: JavaScript Object Methods — Referência rápida com exemplos dos principais métodos de objetos em JavaScript.
- Lodash Documentation: cloneDeep — Documentação oficial do método
cloneDeeppara cópia profunda de objetos. - Dev.to: Understanding Object Spread Operator — Artigo técnico explicando o operador spread em objetos e suas aplicações.