object, Object, {}, new Object() e prototype em JavaScript: um guia completo e direto ao ponto
Em JavaScript, quase tudo gira em torno de objetos. Entender bem como `object`, `Object`, `{}`, `new Object()` e `prototype` funcionam é essencial para escrever código limpo, previsível e fácil de manter.
Neste artigo, vamos destrinchar esses conceitos de forma prática, mostrando como eles se relacionam e como usá‑los com segurança no dia a dia.
[IMAGEM: illustration-object-object-js-01]
—
## 1. object vs Object: existe diferença?
Sim, e é grande.
### 1.1. `Object` (com “O” maiúsculo)
`Object` é a função construtora nativa do JavaScript. Ela é usada para criar objetos e também é o ponto de partida da cadeia de protótipos da maioria dos objetos.
Alguns usos comuns:
js
// Criando um objeto vazio
const obj1 = new Object();
// Convertendo valores para objeto (pouco usado na prática)
const obj2 = Object(10); // Number object
const obj3 = Object(‘texto’); // String object
// Métodos estáticos importantes
Object.keys(obj1);
Object.values(obj1);
Object.entries(obj1);
Object.assign({}, obj1);
Object.freeze(obj1);
Object.create(proto);
Em resumo: `Object` é uma função construtora + um namespace de utilitários para objetos.
### 1.2. `object` (com “o” minúsculo)
`object` não é uma função, nem um construtor. É apenas o nome do tipo (type) retornado por `typeof`:
js
typeof {} // “object”
typeof [] // “object”
typeof null // “object” (peculiaridade da linguagem)
typeof new Date() // “object”
Ou seja:
– `Object` → a função construtora / tipo de referência base.
– `”object”` → o valor string que descreve o tipo, retornado por `typeof`.
[IMAGEM: illustration-object-object-js-02]
—
## 2. Criando objetos: `{}` vs `new Object()`
Na prática, as duas formas criam um objeto, mas não são equivalentes em todos os aspectos.
### 2.1. Sintaxe literal: `{}`
É a forma mais comum e recomendada:
js
const pessoa = {
nome: ‘Ana’,
idade: 30,
falar() {
console.log(`Olá, eu sou ${this.nome}`);
}
};
Vantagens:
– Sintaxe curta e clara.
– Mais performática na maioria dos engines.
– Facilita a leitura e manutenção.
### 2.2. Construtor: `new Object()`
js
const pessoa = new Object();
pessoa.nome = ‘Ana’;
pessoa.idade = 30;
pessoa.falar = function() {
console.log(`Olá, eu sou ${this.nome}`);
};
É funcional, mas raramente é a melhor opção hoje. Usa‑se mais em contextos específicos (APIs antigas, metaprogramação muito específica, ou quando se precisa de algo como `Object.create()` para controlar o protótipo).
### 2.3. Quando usar cada um?
– Para criar objetos “normais” → use `{}`.
– Para criar objetos com protótipo customizado → use `Object.create(proto)`.
– `new Object()` quase nunca é necessário em código moderno.
—
## 3. Entendendo `prototype` e a cadeia de protótipos
O sistema de herança de JavaScript é baseado em protótipos. Todo objeto possui uma referência interna para outro objeto chamado de **protótipo**.
### 3.1. `Object.prototype`
`Object.prototype` é o topo da maior parte da cadeia de protótipos em JavaScript:
js
const obj = {};
Object.getPrototypeOf(obj) === Object.prototype; // true
Tudo o que está em `Object.prototype` fica disponível para praticamente todos os objetos “normais”:
js
obj.hasOwnProperty(‘x’);
obj.toString();
obj.valueOf();
Esses métodos não estão “dentro” do `obj` diretamente, mas sim no seu protótipo.
### 3.2. `prototype` em funções construtoras
Quando você cria uma função construtora, ela ganha automaticamente uma propriedade `prototype`. Objetos criados com `new` a partir dessa função vão “apontar” para esse `prototype`:
js
function Pessoa(nome) {
this.nome = nome;
}
Pessoa.prototype.falar = function() {
console.log(`Olá, eu sou ${this.nome}`);
};
const ana = new Pessoa(‘Ana’);
ana.falar(); // “Olá, eu sou Ana”
Neste exemplo:
– `ana` tem `nome` como propriedade própria.
– `falar` vive em `Pessoa.prototype`.
– `ana` acessa `falar` via cadeia de protótipos.
### 3.3. Cadeia de protótipos (prototype chain)
Visualmente, algo assim:
txt
ana –> Pessoa.prototype –> Object.prototype –> null
– Se você acessa `ana.falar`, o motor JS procura:
1. Em `ana` → não encontrou
2. Em `Pessoa.prototype` → encontrou!
– Se você acessa `ana.toString`, ele procura:
1. Em `ana` → não
2. Em `Pessoa.prototype` → não
3. Em `Object.prototype` → sim
Se chegar em `null`, a busca termina.
—
## 4. Criando objetos com protótipo customizado
### 4.1. `Object.create(proto)`
Forma moderna e clara de configurar o protótipo:
js
const animal = {
tipo: ‘desconhecido’,
falar() {
console.log(`Sou um ${this.tipo}`);
}
};
const cachorro = Object.create(animal); // protótipo = animal
cachorro.tipo = ‘cachorro’;
cachorro.falar(); // “Sou um cachorro”
Cadeia aqui:
txt
cachorro –> animal –> Object.prototype –> null
### 4.2. Por que isso importa?
Entender protótipos ajuda a:
– Evitar sobrescrever coisas no protótipo global (anti‑pattern séria).
– Saber de onde vêm métodos “mágicos” como `map`, `filter`, `toString`, etc.
– Desenhar melhores APIs orientadas a objetos (quando necessário).
– Otimizar memória compartilhando métodos em vez de recriá‑los em cada instância.
—
## 5. Cuidados com objetos e protótipos
### 5.1. Não modifique `Object.prototype`
Mexer em `Object.prototype` quase sempre é má ideia:
js
Object.prototype.meuMetodo = function() {
// …
};
Problemas:
– Você “polui” todos os objetos do sistema.
– Pode quebrar bibliotecas de terceiros que esperam um ambiente limpo.
– Métodos como `for…in` começam a iterar essas propriedades extras.
Prefira sempre:
– Criar seu próprio protótipo ou
– Criar funções utilitárias puras.
### 5.2. Atenção ao `__proto__` (deprecated/legacy)
Embora ainda funcione na maioria dos ambientes, `__proto__` é legado:
js
const obj = {};
console.log(obj.__proto__ === Object.prototype); // true
Use em vez disso:
js
Object.getPrototypeOf(obj);
Object.setPrototypeOf(obj, novoProto); // ainda assim, use com parcimônia
—
## 6. Resumindo os conceitos
– `Object`
Construtor nativo e namespace de métodos utilitários para manipulação de objetos e protótipos.
– `”object”`
String de tipo retornada por `typeof`. Não é função, não é classe.
– `{}`
Sintaxe literal recomendada para criar objetos na maioria dos casos.
– `new Object()`
Forma construtiva equivalente a `{}`, mas quase sempre desnecessária.
– `prototype`
Objeto usado como base de herança para instâncias criadas a partir de um construtor.
– `Object.prototype`
Topo da cadeia de protótipos de quase todos os objetos comuns.
—
## 7. Boas práticas para o dia a dia
1. **Prefira literais**
Use `{}` para objetos e `[]` para arrays, em vez de construtores.
2. **Use `Object.create()` quando precisar de herança simples**
Ajuda a montar protótipos de forma clara.
3. **Nunca polua `Object.prototype`**
Se precisar muito de algo “global”, crie seu próprio namespace.
4. **Use os métodos estáticos de `Object` sem medo**
`Object.keys`, `Object.values`, `Object.entries`, `Object.assign`, `Object.freeze`, `Object.seal`, `Object.create`, etc., são extremamente úteis.
5. **Entenda a chain, mas use classes quando fizer sentido**
Em código moderno, `class` é apenas açúcar sintático sobre protótipos, mas torna o código mais legível para quem vem de linguagens OO clássicas.
—
Com essa base sólida sobre `object`, `Object`, `{}`, `new Object()` e `prototype`, você já está melhor preparado para entender tanto o código moderno (com `class`) quanto o legado (com funções construtoras e manipulação explícita de protótipos).