Skip to main content

Command Palette

Search for a command to run...

Lesson 26: Mastering JavaScript Objects basics with challenges!

Published
β€’8 min readβ€’View as Markdown

What are JavaScript Objects?

Objects are dynamic collections of key-value pairs, where:

  • Keys (aka property names) are always strings or symbols.

  • Values can be of any type (primitives, objects, functions, etc.).

Objects are non-primitive and mutable. They're used everywhere in JS β€” from user-defined structures to built-in types like Array, Date, Error, etc.

let user = {
  name: "Alice",
  age: 28
};

🧱 2. Deep Internal Breakdown

Object Creation:

  • Literal syntax: let obj = { key: value };

  • Constructor: let obj = new Object();

Accessing / Modifying:

  • Dot notation: obj.key β€” only works for valid identifiers.

  • Bracket notation: obj["complex key"] β€” supports any string.

Dynamic property names (Computed):

let fruit = "apple";
let bag = {
  [fruit]: 5 // same as: bag.apple = 5
};

Shorthand:

let name = "John";
let user = { name }; // same as { name: name }

Property keys:

All keys are strings internally:

let obj = { 1: "a" };
console.log(obj["1"]); // "a"

Special property: __proto__

  • A getter/setter for the prototype.

  • Cannot be overwritten by primitives.

obj.__proto__ = 5; // silently ignored

Property Existence:

  • obj.key === undefined βœ…

  • "key" in obj βœ… (even if value is undefined)

Iteration: for..in

  • Loops over enumerable own + inherited properties

  • Key order:

    • Integer-like keys β†’ sorted numerically.

    • Others β†’ insertion order.

let obj = { "2": "two", "1": "one" }; // prints 1, 2

🧠 Internal Mechanics

  • Objects are internally implemented as hash tables (property-key map).

  • Property lookup time is amortized O(1) unless prototype chains grow deep.

  • Hidden classes (in V8) optimize repeated object shape usage (same properties in same order) β€” objects with same β€œshape” are faster.

πŸ’₯ Commonly Missed Subtopics & Gotchas

πŸ”Έ __proto__ is not just a property

It behaves differently:

obj.__proto__ = null; // modifies prototype chain

If you want to safely add __proto__ as a normal property, use:

Object.create(null)

It creates an object with no prototype.

πŸ”Έ Property Enumeration Traps

for..in iterates enumerable inherited properties, while:

  • Object.keys() β†’ own enumerable properties

  • Object.getOwnPropertyNames() β†’ own properties (enumerable or not)

  • Reflect.ownKeys() β†’ includes symbols

πŸ”Έ Numeric vs String keys

let obj = { "1": "a", 1: "b" };
console.log(obj["1"]); // b – overwrites previous value

πŸ”Έ Non-Enumerable Properties Are Invisible to for..in

jsCopyEditlet obj = {};
Object.defineProperty(obj, "hidden", {
  value: "invisible",
  enumerable: false
});

πŸ”Έ Don’t Use Objects as Maps!

let map = {};
map["__proto__"] = "bad"; // prototype pollution!

Use Map if keys are dynamic and may collide with built-ins.

πŸ”Έ Functions are Objects too!

function greet() {}
greet.language = "English";

πŸ’» Browser-Specific Quirks

Older IE (≀9) had issues with object enumeration order (non-standard). Modern browsers now follow spec:

  • Integer-like keys β†’ sorted

  • Strings β†’ insertion order

⚠️ Developers Often Get Wrong:

  • Forgetting square brackets for dynamic keys.

  • Misusing in operator vs undefined check.

  • Relying on property order from for..in or Object.keys() without realizing sorting rules.

  • Expecting objects to behave like Maps or arrays.

  • Trying to delete non-configurable properties.

⚠️ Sub-Concepts Often Missed

βœ… 1. Keys are Strings or Symbols β€” Always

let obj = {};
obj[{}] = "val";
console.log(Object.keys(obj)); // ["[object Object]"]

All non-symbol keys are coerced to strings. Even objects. Only Symbol() avoids this.


βœ… 2. Own vs Inherited Properties

for..in includes inherited enumerable props!

const parent = { a: 1 };
const child = Object.create(parent);
child.b = 2;

for (let key in child) console.log(key); // "b", then "a"

βœ… 3. Non-Enumerable Props

Object.keys() skips non-enumerables:

let obj = {};
Object.defineProperty(obj, "hidden", {
  value: 123,
  enumerable: false
});
console.log(Object.keys(obj)); // []
console.log("hidden" in obj);  // true

βœ… 4. Object.prototype Pollution Risk

Object.prototype.foo = 123;
let obj = {};
console.log("foo" in obj); // true β€” inherited

βœ… Solution: Object.create(null) β€” a truly blank object without a prototype.


βœ… 5. Reserved Keyword Safety (Object Literals)

let obj = {
  let: "valid",
  return: "also valid"
};

Works fine because property names are always strings in object literals, and reserved keywords aren’t restricted there.


βœ… 6. Execution Order Trap: Integer-Like Keys Are Sorted

let obj = {
  100: "a",
  2: "b",
  7: "c"
};
console.log(Object.keys(obj)); // ["2", "7", "100"]

βœ… To preserve insertion order, prefix with a character: "id_2" instead of 2.


🚨 Dev Confusions & Mistakes

MistakeWhy It’s Problematic
Using for..in on arraysIncludes inherited props + wrong order
Assigning to __proto__Alters prototype chain
Using objects for mapsMay collide with hasOwnProperty, toString
Checking key existence with obj[key] === undefinedFails when value is explicitly undefined
Using object keys to store functions or DOM nodesCan lead to memory leaks without proper cleanup

πŸ”₯ 3. Challenge Me Deeply

πŸ’» Task 1: Hello, Object

let user = {}; // Create empty object
user.name = "John"; // Add name
user.surname = "Smith"; // Add surname
user.name = "Pete"; // Modify name
delete user.name; // Remove name

πŸ’» Task 2: isEmpty

function isEmpty(obj) {
  for (let key in obj) return false;
  return true;
}

⚠️ Object.keys(obj).length === 0 is also valid, but for..in avoids temporary array allocation.

πŸ’» Task 3: Sum Salaries

let salaries = {
  John: 100,
  Ann: 160,
  Pete: 130
};

let sum = 0;
for (let key in salaries) {
  sum += salaries[key];
}

πŸ’» Task 4: Multiply Numeric

function multiplyNumeric(obj) {
  for (let key in obj) {
    if (typeof obj[key] === "number") {
      obj[key] *= 2;
    }
  }
}

🎯 4. Interview-Ready Questions

βœ… Basic

  1. What’s the difference between dot and bracket notation?

  2. Can object keys be non-strings?

  3. What does __proto__ do, and why is it special?

🧩 Intermediate

  1. Why might "key" in obj be better than obj.key === undefined?

  2. What is the order of keys in for..in?

  3. What happens when a number is used as a property key?

🧠 Advanced

  1. Why can’t you reliably override __proto__ with a non-object?

  2. How would you deeply clone an object?

  3. Why is it risky to use for..in with arrays?

  4. What are symbols, and why might you use them as keys?


⚠️ 5. Hidden Pitfalls & Edge Cases

PitfallExplanation
obj["key"] !== undefinedDoesn't guarantee the property exists. It could exist with undefined value.
__proto__Has special prototype-binding behavior, unlike regular keys.
Integer-like keysSorted numerically in for..in. Surprising to many!
Bracket notation in obj.keyInterprets "key" as a literal property name. Variables must be used like obj[var].
Symbol keysNot accessible via for..in, only via Object.getOwnPropertySymbols() or Reflect.ownKeys().

πŸ› οΈ 6. Practical Code Patterns

Pattern: Safe property access

if ("key" in obj) {
  // do something
}

Pattern: Clone object

let clone = { ...original }; // shallow

Pattern: Count properties

Object.keys(obj).length;

Pattern: Dynamic key assignment

let key = "age";
let obj = { [key]: 30 };

Real-World Usage

πŸ’‘ In Frameworks:

  • React props/state: All objects.

  • Redux store: State trees are plain objects.

  • Vue reactivity system: Built around property access trapping.

  • Express.js: req.params, res.locals are object-based.

πŸ“¦ In Libraries:

  • Lodash: _.get, _.set, _.has β†’ all work with nested object paths.

  • MongoDB: Query filters are objects.

  • Stripe API, Firebase Config: All config-driven using object literals.

🏭 Production Examples:

  • User profile objects

  • Form schema definitions

  • Config managers

  • Service maps

  • Component registries


πŸ”Ή 6. Remember Like a Pro

πŸ”‘ Mnemonic:

DOTS are simple. BRACKETS are powerful.

  • Dot: Deterministic, Definite, Defined keys

  • Only identifiers

  • Tame strings

  • Short and Sweet


🎯 Cheatsheet (Quick Visual)

FeatureDot NotationBracket Notation
Works with variable keysβŒβœ…
Requires valid identifierβœ…βŒ
Allows spaces/symbolsβŒβœ…

🧠 Mind Map (Core Object Concepts)

                 JavaScript Object
                /       |        \
           Keys      Access      Tools
         /    \      /    \     /     \
     String  Symbol  Dot  Bracket  delete/in/for..in

πŸ”Ή 7. Apply It in a Fun Way

πŸ›  Mini Project: Dynamic Theme Manager

Build a theme switcher where each theme is stored in an object, and properties are dynamically accessed based on user choice.


🧩 Steps:

  1. Create themes object with dark, light, and solarized keys.

  2. Store each theme's colors (bg, text, accent) as nested objects.

  3. Prompt user for theme name β†’ use bracket notation to access theme.

  4. Apply colors to document (in browser or via simulated console log).

  5. Add fallback theme if unknown input is provided.


🧨 Bonus Extensions:

  • Allow runtime addition of new themes.

  • Use Object.keys() to list available themes.

  • Export/import theme configs via JSON.


🧠 (Optional – Extra Value)

βš™οΈ Open-Source Projects Using Objects Heavily:

  • ESLint configs

  • Babel plugins

  • Webpack rules/loaders

  • TailwindCSS theme configuration


🧯 Mistakes Devs Often Make

  • Modifying inherited props accidentally

  • Using delete in hot code paths (it's slow)

  • Using objects as maps without guarding key collisions


🧩 Performance Tips

  • Avoid delete β†’ prefer obj[key] = undefined when performance-critical.

  • Use Map instead of object if keys are dynamic or non-strings.

  • For nested object access, memoize using tools like Lodash or use structured paths.

More from this blog

JS Journey : Concepts & Challenges

57 posts