Create, clone, merge, and transform JavaScript objects with modern syntax and practical patterns.
Object.create for different needs.structuredClone.Object.assign.structuredClone() instead of JSON.parse(JSON.stringify(obj)) to deep-clone, since it handles dates, maps, and other types correctly.Object.hasOwn(obj, 'key') instead of hasOwnProperty() directly, since it works safely even on objects created with Object.create(null).Object.assign() only do shallow copies, so changes to nested objects in the copy will still affect the original.if (obj.key) misfires when the value is legitimately 0 or false.Object LiteralBuilds an object directly from comma-separated key-value pairs in one line.
const user = { name: 'Ava', age: 28 };classDefines a reusable blueprint with shared methods and a constructor.
class User {
constructor(name) { this.name = name; }
}Object.create()Creates an object that inherits directly from a given prototype object.
const proto = { greet() { return 'Hi!'; } };
const user = Object.create(proto);Computed PropertySets a dynamic key name using bracket syntax inside an object literal.
const key = 'role';
const user = { [key]: 'admin' };Dot NotationReads or writes a property using a fixed, known key name.
console.log(user.name); // 'Ava'Bracket NotationReads a property using a variable or a name with special characters.
console.log(user['role']); // dynamic key okOptional ChainingSafely reads a deeply nested property without throwing if it's missing.
console.log(user?.address?.city);Nullish CoalescingProvides a fallback value only when the left side is null or undefined.
console.log(user.phone ?? 'N/A');deleteRemoves a property from an object entirely, including its key.
delete user.temp; // removes the propertyObject.keys()Returns an array of an object's own enumerable property names.
Object.keys({ a: 1, b: 2 }); // ['a', 'b']Object.values()Returns an array of just the object's own property values.
Object.values({ a: 1, b: 2 }); // [1, 2]Object.entries()Returns an array of [key, value] pairs for looping or transforms.
Object.entries({ a: 1 }); // [['a', 1]]for...inLoops over enumerable keys, including any inherited from the prototype.
for (const key in user) {
console.log(key);
}Object.hasOwn()Checks whether an object owns a given key, ignoring inherited ones.
Object.hasOwn(user, 'name'); // trueSpreadCreates a shallow copy with every enumerable own property copied over.
const copy = { ...original };Object.assign()Copies properties into a new target object; also works for merging.
const copy = Object.assign({}, original);structuredClone()Deep-clones nested objects, Dates, Maps, and Sets without shared references.
const deep = structuredClone(original);Spread MergeMerges objects into a new one; later keys overwrite earlier matches.
const merged = { ...base, ...extra };Object.assign(target, source)Merges source properties directly into an existing target object in place.
Object.assign(base, extra); // mutates baseObject.fromEntries()Builds an object from an array of [key, value] pairs for fast lookups.
const map = Object.fromEntries(
users.map(u => [u.id, u])
);entries() + map()Converts an object back into an array to transform or filter it.
Object.entries(user).map(([k, v]) => `${k}:${v}`);Use structuredClone(obj), which natively handles Dates, Maps, Sets, RegExp, and typed arrays. JSON.parse(JSON.stringify()) silently corrupts Dates into strings and drops undefined values entirely.
Both produce a shallow merge, but Object.assign() mutates the target in place, while spread ({...a, ...b}) returns a new object. Prefer spread to avoid modifying an existing object by accident.
Use Object.entries(obj) with for...of to destructure each pair: for (const [key, val] of Object.entries(obj)). Use Object.keys() or Object.values() when you only need one side.
Use computed property syntax directly in the literal: { [variableName]: value }. This is cleaner than creating the object first and then assigning with bracket notation afterward.
Use Object.hasOwn(obj, 'key') for own properties (ES2022), or the in operator to include inherited ones. Avoid relying on truthiness like if (obj.key), since a property can legitimately hold 0, false, or null.
Merge Settings and Build a Lookup
Merges user setting overrides onto defaults, then builds an id-keyed lookup map with Object.fromEntries().
overrides on top of defaults, so later keys always win.Object.fromEntries() turns the users array into an id-keyed lookup map.??) supplies a fallback only when a value is missing.?.) reads byId[9] safely even though that id doesn't exist.const defaults = { theme: 'light', notifications: true };
const overrides = { theme: 'dark', fontSize: 14 };
const settings = { ...defaults, ...overrides };
const users = [
{ id: 1, name: 'Ava', role: 'admin' },
{ id: 2, name: 'Noah', role: 'editor' },
{ id: 3, name: 'Mia', role: 'viewer' },
];
const byId = Object.fromEntries(users.map(u => [u.id, u]));
console.log(settings.theme); // 'dark'
console.log(settings.fontSize ?? 12); // 14
console.log(byId[2]?.name); // 'Noah'
console.log(byId[9]?.name ?? 'N/A'); // 'N/A'Spread later objects last so their keys win, and use Object.fromEntries() for instant id-based lookups.