Skip to main content

Ways to declare an object

JavaScript has several ways to create an object, and the choice depends on what you actually need: a plain object, a copy, a template or a class instance. They all produce the same data type, but differ in how the prototype is set and how much boilerplate you have to write.

Theory

TL;DR

  • The {} literal is the shortest and most common way in real code.
  • new Object() does the same thing but is longer, so it is almost never used.
  • Object.create(proto) creates an object with a given prototype.
  • A constructor function with new and a class create instances of a certain "type".
  • Spread ({ ...base }) creates a copy of an existing object with new properties.
  • Object.fromEntries() builds an object from "key -> value" pairs.

Quick example

javascript
const user = { name: 'Tim', age: 25 };

A literal creates a new object with the needed properties right away. This is the most widespread way in real code: short, readable and free of ceremony.

The literal and the Object constructor

Through the constructor the same object looks like this:

javascript
const user = new Object(); user.name = 'Tim'; user.age = 25;

It works, but it is usually not recommended: literals ({}) are shorter and clearer, and the result is identical. new Object() shows up mostly in old code or for compatibility.

Object.create(proto)

This way lets you create an object with a specific prototype:

javascript
const person = { species: 'human' }; const user = Object.create(person); user.name = 'Tim'; console.log(user.species); // "human" (inherited from person)

It is used in advanced scenarios where the prototype chain is managed by hand. One separate useful case is Object.create(null): an object with no prototype at all, handy as a dictionary.

A constructor function and class

Constructor functions (called with new) create objects of a certain "type" and automatically set this to the new object:

javascript
function User(name, age) { this.name = name; this.age = age; } const tim = new User('Tim', 25); console.log(tim.name); // "Tim"

A class is syntactic sugar over a constructor function, and it is what modern JS uses:

javascript
class User { constructor(name, age) { this.name = name; this.age = age; } } const tim = new User('Tim', 25); console.log(tim.name); // "Tim"

Both variants produce instances that share a prototype, so methods are stored once instead of being copied into every object.

Spread and Object.fromEntries()

Spread creates a copy of an existing object with new properties added:

javascript
const base = { role: 'user' }; const user = { ...base, name: 'Tim', age: 25 };

Object.fromEntries() assembles an object from an array of pairs, which is useful after Object.entries() or when working with a Map:

javascript
const entries = [['name', 'Tim'], ['age', 25]]; const user = Object.fromEntries(entries); console.log(user); // { name: 'Tim', age: 25 }

Summary table

WayExampleWhen to use it
Literal {}{ name: 'Tim' }the most common way
new Object()new Object()rarely, for compatibility
Object.create(proto)Object.create(person)when you need prototype control
Constructor functionnew User()the old but working approach
classnew User()the modern, OOP approach
Spread, a copy{ ...obj }duplicating and extending objects
Object.fromEntries()Object.fromEntries(pairs)building from "key -> value" pairs

In one sentence: an object in JS can be created in many ways, from a plain {} to a class, but in 95% of cases the {} literal is enough, or a class for structured data.

Common mistakes

  • Writing new Object() instead of {}. The result is the same, but there is more code and less readability.
  • Confusing Object.create(person) with copying. The properties of person are not copied, they are inherited, so a change to the prototype is immediately visible in every descendant.
  • Calling a constructor function without new. Then this is not a new object, the function returns undefined, and in sloppy mode it also pollutes the global object.
  • Treating { ...base } as a deep copy. Spread copies only the top level, nested objects stay shared.
  • Expecting spread to copy the prototype. Only own enumerable properties are spread, so a class instance becomes a plain object with no methods.
  • Using a plain object as a dictionary for arbitrary keys. Keys such as constructor or toString clash with the prototype; Object.create(null) or a Map fits better there.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.