Object Methods

Reviewed & published by Brayan K

The static Object methods — keys, values, entries, assign, and freeze — let you inspect, transform, merge, and protect plain objects without manual loops.

Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

They turn objects into something you can iterate and reshape with the same array tools you already know.

What You'll Learn in This Lesson

📚 Prerequisites: You should be comfortable with objects and array methods like map and reduce. Many object tasks become array tasks once you call Object.entries.

🗝️ Real-World Analogy: Think of an object as a labeled filing cabinet:

1️⃣ Iterating: keys, values, entries & fromEntries

Plain objects aren't directly iterable, but these three convert them into arrays you can loop and transform. Object.entries pairs with destructuring in a for...of loop, and Object.fromEntries does the reverse — turning [key, value] pairs back into an object. Together they let you map/filter an object as if it were an array.

Transform pattern: entries → map → fromEntries is the standard way to build a new object from an old one — like doubling every value or renaming keys.

const prices = { pen: 2, mug: 9, bag: 25 };

console.log(Object.keys(prices));   // ✅ Expected output: [ 'pen', 'mug', 'bag' ]
console.log(Object.values(prices)); // ✅ Expected output: [ 2, 9, 25 ]

// Loop entries with destructuring
for (const [name, price] of Object.entries(prices)) {
  console.log(name + ": $" + price);
}
// ✅ Expected output:
// pen: $2
// mug: $9
// bag: $25

// entries → map → fromEntries to apply a 10% rise
const raised = Object.fromEntries(
  Object.entries(prices).map(([k, v]) => [k, v * 1.1])
);
console.log(raised.bag); // ✅ Expected output: 27.500000000000004

2️⃣ Merging & Protecting: assign, spread, freeze

Object.assign(target, ...sources) copies properties into a target (and returns it). The spread form { ...a, ...b } does the same but always creates a fresh object — usually the safer choice. Later sources win on key conflicts. Object.freeze makes an object read-only; Object.isFrozen reports whether it's locked.

freeze is shallow: a nested object inside a frozen object can still be changed. Freeze each level if you need deep immutability.

const defaults = { theme: "light", size: "md" };
const user = { theme: "dark" };

// Spread merge — later object wins
const settings = { ...defaults, ...user };
console.log(settings);          // ✅ Expected output: { theme: 'dark', size: 'md' }

// Object.assign mutates and returns the target
const target = { a: 1 };
Object.assign(target, { b: 2 }, { a: 9 });
console.log(target);            // ✅ Expected output: { a: 9, b: 2 }

const config = Object.freeze({ retries: 3 });
config.retries = 99;            // ignored (not strict mode here)
console.log(config.retries);   // ✅ Expected output: 3
console.log(Object.isFrozen(config)); // ✅ Expected output: true

3️⃣ Deep Copy with structuredClone & Object.groupBy

Spread and assign only copy one level deep — nested objects stay shared. When you truly need an independent copy, structuredClone recursively clones the whole structure. Object.groupBy (ES2024) buckets an array into an object keyed by whatever your callback returns, which is the cleanest way to categorize data.

structuredClone limits: it can't clone functions, DOM nodes, or class instances with methods — it's for plain data (objects, arrays, dates, maps, sets).

const original = { user: { name: "Ada", tags: ["a"] } };

// Shallow spread shares the nested object...
const shallow = { ...original };
shallow.user.name = "CHANGED";
console.log(original.user.name); // ✅ Expected output: CHANGED  (shared!)

// structuredClone is fully independent
const data = { user: { name: "Ada" } };
const deep = structuredClone(data);
deep.user.name = "Grace";
console.log(data.user.name);     // ✅ Expected output: Ada  (untouched)

// Object.groupBy buckets items by a key
const nums = [1, 2, 3, 4, 5];
const grouped = Object.groupBy(nums, n => (n % 2 ? "odd" : "even"));
console.log(grouped.odd);        // ✅ Expected output: [ 1, 3, 5 ]
console.log(grouped.even);       // ✅ Expected output: [ 2, 4 ]

🎯 Your Turn — List the Values

Use the right method to get an array of all the values in the object.

const scores = { math: 90, art: 75, gym: 88 };

// 👉 replace ___ with the method that returns just the values
const list = Object.___(scores);

console.log(list);
// ✅ Expected output: [ 90, 75, 88 ]

🧠 Quick Recall

Predict the output before revealing the answer.

2 — there are two own enumerable keys.

{ a: 2 } — the later spread wins on a key conflict.

1 — the object is frozen, so the assignment is ignored.

Common Errors & Fixes

🎯 Mini Challenge — Invert a Lookup

Swap keys and values of a small dictionary using entries, map, and fromEntries.

const codes = { US: "United States", FR: "France" };

// 👉 build a new object where the value becomes the key
const inverted = Object.fromEntries(
  Object.entries(codes).map(([k, v]) => [v, k])
);

console.log(inverted["France"]); // ✅ Expected output: FR
console.log(inverted["United States"]); // ✅ Expected output: US

Quick Reference

MethodPurpose
keys/values/entriesobject → arrays
fromEntriespairs → object
assign / spreadmerge (shallow)
freeze / isFrozenmake read-only / check
structuredClonedeep copy
groupBybucket by key

📚 Keep Learning

🎉 Lesson Complete — Object Methods!

Practice quiz

What does Object.keys({ a: 1, b: 2 }) return?

  • [1, 2]
  • [['a',1],['b',2]]
  • ['a', 'b']
  • { a: 1, b: 2 }

Answer: ['a', 'b']. Object.keys returns an array of the property names: ['a', 'b'].

What does Object.values({ a: 1, b: 2 }) return?

  • [1, 2]
  • ['a', 'b']
  • [['a',1],['b',2]]
  • 2

Answer: [1, 2]. Object.values returns an array of the values: [1, 2].

What does Object.entries({ a: 1, b: 2 }) return?

  • ['a', 'b']
  • [1, 2]
  • { a: 1, b: 2 }
  • [['a', 1], ['b', 2]]

Answer: [['a', 1], ['b', 2]]. Object.entries returns an array of [key, value] pairs: [['a', 1], ['b', 2]].

Which method turns [[key, value]] pairs back into an object?

  • Object.keys
  • Object.fromEntries
  • Object.assign
  • Object.values

Answer: Object.fromEntries. Object.fromEntries is the reverse of entries, building an object from [key, value] pairs.

What is the standard pattern to build a new object from an old one?

  • entries → map → fromEntries
  • keys → filter → join
  • values → reduce
  • freeze → clone

Answer: entries → map → fromEntries. entries → map → fromEntries is the standard way to transform an object's keys or values.

In { ...{ a: 1 }, ...{ a: 2 } }, what is the value of a?

  • 1
  • [1, 2]
  • 2
  • undefined

Answer: 2. On a key conflict, the later spread wins, so a is 2.

Is Object.freeze shallow or deep?

  • Deep — it freezes nested objects too
  • Shallow — nested objects can still be changed
  • It only freezes arrays
  • It throws on nested objects

Answer: Shallow — nested objects can still be changed. freeze is shallow; nested objects inside a frozen object remain mutable.

After const f = Object.freeze({ n: 1 }); f.n = 5; what is f.n?

  • 5
  • undefined
  • It throws
  • 1

Answer: 1. The object is frozen, so the assignment is ignored (silently here) and f.n stays 1.

Why use structuredClone instead of spread for a nested object?

  • It is shorter
  • spread is a shallow copy that shares nested objects; structuredClone copies deeply
  • structuredClone is faster for everything
  • spread can't copy arrays

Answer: spread is a shallow copy that shares nested objects; structuredClone copies deeply. Spread shares nested references; structuredClone makes a true deep, independent copy.

What does Object.groupBy([1, 2, 3, 4, 5], n => n % 2 ? 'odd' : 'even') return for the 'odd' key?

  • [2, 4]
  • [1, 2, 3, 4, 5]
  • [1, 3, 5]
  • 3

Answer: [1, 3, 5]. Object.groupBy buckets items by the callback's key, so 'odd' holds [1, 3, 5].

Continue this course

Frequently asked questions

What is the difference between Object.keys, values, and entries?

Object.keys returns an array of the property names, Object.values returns an array of the values, and Object.entries returns an array of [key, value] pairs. entries is especially handy because you can loop it with for...of and destructuring, or feed it through array methods like map and filter.

Does Object.freeze make an object deeply immutable?

No. freeze is shallow — it locks the top-level properties, but nested objects are still mutable. To freeze deeply you must recursively freeze each nested object, or use a dedicated deep-freeze utility.

When should I use structuredClone instead of spread?

Spread ({...obj}) and Object.assign make a SHALLOW copy: nested objects are shared by reference. structuredClone makes a true DEEP copy, so editing a nested property on the clone never touches the original. Use it whenever your object contains nested objects or arrays you need to copy independently.

What does Object.groupBy do?

Object.groupBy (ES2024) takes an iterable and a callback that returns a group key for each item, then returns an object whose keys are those group names and whose values are arrays of the matching items. It is the clean, built-in way to bucket data — for example grouping orders by status.