✅ Objects
You’ve already learned what an object is and how to create one using the object literal syntax.
An object literal is the simplest way to build an object by directly writing its properties inside curly braces.
Example:
const car = {
brand: "Honda",
model: "City",
start() {
console.log("Car started");
}
};
console.log(car.brand); // Honda
car.start(); // Car started✅ Factory Function
A factory function is a normal function that creates and returns a new object every time it is called. Easy way to create multiple similar objects.
✔️ No class
✔️ No new keyword
✔️ Just a function that produces objects — like a factory!
Simple Example
function createUser(name, age) {
return {
name,
age,
greet() {
console.log(`Hi, I'm ${name}`);
}
};
}
const user1 = createUser("Bhaskar", 25);
const user2 = createUser("Tisha", 30);
user1.greet(); // Hi, I'm Bhaskar
user2.greet(); // Hi, I'm TishaWhat’s happening?
Calling
createUser()returns a fresh objectEach object has its own properties and methods
No need for
new
✅ Real World Use Case: Private Data Example (Closure)
function createCounter() {
let count = 0; // private
return {
increment() {
count++;
console.log(count);
}
};
}
const counter = createCounter();
counter.increment(); // 1
counter.increment(); // 2✅ count cannot be accessed directly — only through methods.
❗️ Constructor Function
A constructor function is a special type of function used to create objects in JavaScript using the new keyword.
✔️ Starts with a capital letter
✔️ Uses this to set properties
✔️ Automatically returns the new object
It’s basically a blueprint for creating multiple similar objects.
Simple Example
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function () {
console.log(`Hi, I'm ${this.name}`);
};
}
const user1 = new Person("Bhaskar", 30);
const user2 = new Person("Tisha", 24);
user1.greet(); // Hi, I'm Bhaskar
user2.greet(); // Hi, I'm TishaWhat’s happening?
new Person()creates a new objectthis.nameandthis.ageassign values to that objectNo need to write
return— JavaScript does it automatically
<div class="infographic-fc">
<style>
.infographic-fc {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #1a8a5f;
--bad: #c8452e;
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
font-family: 'Inter', system-ui, sans-serif;
color: var(--ink);
background: var(--paper);
}
.infographic-fc[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4fbf8f;
--bad: #e0715a;
}
.infographic-fc * { box-sizing: border-box; }
.infographic-fc h1, .infographic-fc h2 { font-family: 'Fraunces', Georgia, serif; font-weight: 600; margin: 0; }
.infographic-fc p { margin: 0; }
.infographic-fc button { font-family: inherit; }
.fc-wrap { padding: 0 clamp(1.25rem, 5vw, 3rem); }
.fc-hero { text-align: center; padding: 2.25rem 0 1.75rem; border-bottom: 1px solid var(--line); }
.fc-hero h1 { font-size: clamp(1.6rem, 5vw, 2.3rem); }
.fc-hero p { color: var(--ink-soft); margin-top: 0.5rem; font-size: 0.95rem; }
.fc-section { padding: 2rem 0; border-bottom: 1px solid var(--line); }
.fc-section:last-child { border-bottom: none; }
/* Two build lanes side by side */
.lanes { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--line); border: 1px solid var(--line); }
@media (max-width: 680px) { .lanes { grid-template-columns: 1fr; } }
.lane { background: var(--paper); padding: 1.25rem 1rem 1.5rem; }
.lane-head { text-align: center; margin-bottom: 0.9rem; }
.lane-head svg { width: 24px; height: 24px; stroke: var(--accent); }
.lane-head h2 { font-size: 1.1rem; margin-top: 0.3rem; }
.lane-head .lane-code { display: block; font-family: 'IBM Plex Mono', monospace; font-size: 0.72rem; color: var(--ink-soft); margin-top: 0.15rem; }
.track { position: relative; display: flex; align-items: center; justify-content: space-between; min-height: 150px; padding: 0 0.25rem; }
.stepdot { display: flex; flex-direction: column; align-items: center; gap: 0.35rem; flex: 1; position: relative; z-index: 2; }
.stepdot .dot-icon { width: 34px; height: 34px; border-radius: 50%; border: 1.5px solid var(--line); background: var(--paper-alt); display: flex; align-items: center; justify-content: center; transition: border-color 0.25s, background 0.25s, transform 0.25s; }
.stepdot .dot-icon svg { width: 16px; height: 16px; stroke: var(--ink-soft); transition: stroke 0.25s; }
.stepdot .dot-label { font-size: 0.62rem; text-align: center; color: var(--ink-soft); line-height: 1.25; max-width: 66px; }
.stepdot.is-lit .dot-icon { border-color: var(--accent); background: var(--accent-soft); transform: scale(1.12); }
.stepdot.is-lit .dot-icon svg { stroke: var(--accent); }
.stepdot.is-lit .dot-label { color: var(--ink); font-weight: 600; }
.track-line { position: absolute; left: 5%; right: 5%; top: 17px; height: 2px; background: var(--line); z-index: 1; }
.track-fill { position: absolute; left: 5%; top: 17px; height: 2px; width: 0%; background: var(--accent); z-index: 1; transition: width 0.9s ease; }
.out-row { display: flex; align-items: center; justify-content: center; gap: 0.6rem; margin-top: 0.75rem; }
.out-box { width: 108px; border: 1.5px solid var(--line); background: var(--paper-alt); padding: 0.55rem; text-align: center; opacity: 0.35; transition: opacity 0.3s ease, border-color 0.3s ease; }
.out-box.is-ready { opacity: 1; border-color: var(--good); }
.out-box .out-title { font-family: 'IBM Plex Mono', monospace; font-size: 0.68rem; font-weight: 700; }
.out-box .out-sub { font-size: 0.62rem; color: var(--ink-soft); margin-top: 0.1rem; }
.lane-play { display: block; margin: 1rem auto 0; border: none; background: var(--accent); color: #fff; padding: 0.5rem 1.3rem; font-size: 0.8rem; font-weight: 600; cursor: pointer; }
.lane-play:active { transform: scale(0.97); }
/* Comparison chip row */
.chips { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--line); border: 1px solid var(--line); margin-top: 0; }
@media (max-width: 680px) { .chips { grid-template-columns: 1fr; } }
.chip-row { display: contents; }
.chip-row .chip-label { grid-column: 1 / -1; background: var(--paper-alt); text-align: center; font-size: 0.72rem; color: var(--ink-soft); padding: 0.4rem; font-weight: 600; letter-spacing: 0.02em; }
.chip { background: var(--paper); padding: 0.7rem 0.5rem; display: flex; align-items: center; justify-content: center; gap: 0.4rem; font-size: 0.78rem; }
.chip svg { width: 15px; height: 15px; flex-shrink: 0; }
.chip.yes svg { stroke: var(--good); }
.chip.no svg { stroke: var(--bad); }
@media (prefers-reduced-motion: reduce) {
.infographic-fc *, .infographic-fc *::before, .infographic-fc *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="fc-wrap">
<div class="fc-hero">
<h1>Constructor vs Factory Functions</h1>
<p>Two ways to hand out objects. Press play and watch each one build.</p>
</div>
<div class="fc-section">
<div class="lanes">
<!-- Constructor lane -->
<div class="lane" id="laneCtor">
<div class="lane-head">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 4V2"/><path d="M15 16v-2"/><path d="M8 9h2"/><path d="M20 9h2"/><path d="M17.8 11.8 19 13"/><path d="M15 9h.01"/><path d="M17.8 6.2 19 5"/><path d="m3 21 9-9"/><path d="M12.2 6.2 11 5"/></svg>
<h2>Constructor</h2>
<code class="lane-code">new Car("red")</code>
</div>
<div class="track">
<div class="track-line"></div>
<div class="track-fill" id="ctorFill"></div>
<div class="stepdot" data-step="1">
<div class="dot-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"/></svg></div>
<div class="dot-label">"new" makes {}</div>
</div>
<div class="stepdot" data-step="2">
<div class="dot-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="5"/><path d="M20 21a8 8 0 0 0-16 0"/></svg></div>
<div class="dot-label">this = {}</div>
</div>
<div class="stepdot" data-step="3">
<div class="dot-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z"/></svg></div>
<div class="dot-label">this.color = "red"</div>
</div>
<div class="stepdot" data-step="4">
<div class="dot-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></div>
<div class="dot-label">this comes back — no return needed</div>
</div>
</div>
<div class="out-row">
<div class="out-box" id="ctorOut">
<div class="out-title">myCar</div>
<div class="out-sub">color: "red"</div>
</div>
</div>
<button class="lane-play" data-lane="ctor" type="button">Play</button>
</div>
<!-- Factory lane -->
<div class="lane" id="laneFactory">
<div class="lane-head">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 16h.01"/><path d="M16 16h.01"/><path d="M3 19a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8.5a.5.5 0 0 0-.769-.422l-4.462 2.844A.5.5 0 0 1 15 10.5v-2a.5.5 0 0 0-.769-.422L9.77 10.922A.5.5 0 0 1 9 10.5V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z"/><path d="M8 16h.01"/></svg>
<h2>Factory</h2>
<code class="lane-code">createCar("red")</code>
</div>
<div class="track">
<div class="track-line"></div>
<div class="track-fill" id="factFill"></div>
<div class="stepdot" data-step="1">
<div class="dot-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="6 3 20 12 6 21 6 3"/></svg></div>
<div class="dot-label">plain function call</div>
</div>
<div class="stepdot" data-step="2">
<div class="dot-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/></svg></div>
<div class="dot-label">const obj = {}</div>
</div>
<div class="stepdot" data-step="3">
<div class="dot-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z"/></svg></div>
<div class="dot-label">obj.color = "red"</div>
</div>
<div class="stepdot" data-step="4">
<div class="dot-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg></div>
<div class="dot-label">return obj — spelled out</div>
</div>
</div>
<div class="out-row">
<div class="out-box" id="factOut">
<div class="out-title">myCar</div>
<div class="out-sub">color: "red"</div>
</div>
</div>
<button class="lane-play" data-lane="fact" type="button">Play</button>
</div>
</div>
</div>
<div class="fc-section">
<div class="chips">
<div class="chip-row">
<div class="chip-label">needs "new"</div>
</div>
<div class="chip yes"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg> Constructor</div>
<div class="chip no"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg> Factory</div>
<div class="chip-row">
<div class="chip-label">explicit return</div>
</div>
<div class="chip no"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg> Constructor</div>
<div class="chip yes"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg> Factory</div>
<div class="chip-row">
<div class="chip-label">forget the keyword and it breaks</div>
</div>
<div class="chip yes"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg> Constructor</div>
<div class="chip no"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg> Factory</div>
</div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-fc')
|| document.querySelector('.infographic-fc');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
function playLane(laneId, fillId, outId) {
const lane = wrapper.querySelector('#' + laneId);
const fill = wrapper.querySelector('#' + fillId);
const out = wrapper.querySelector('#' + outId);
const dots = lane.querySelectorAll('.stepdot');
dots.forEach(d => d.classList.remove('is-lit'));
out.classList.remove('is-ready');
fill.style.transition = 'none';
fill.style.width = '0%';
void fill.offsetWidth;
fill.style.transition = 'width 0.9s ease';
const stepDelay = 550;
dots.forEach((dot, i) => {
setTimeout(() => {
dot.classList.add('is-lit');
const pct = ((i + 1) / dots.length) * 90;
fill.style.width = pct + '%';
}, i * stepDelay);
});
setTimeout(() => {
fill.style.width = '90%';
out.classList.add('is-ready');
}, dots.length * stepDelay);
}
wrapper.querySelectorAll('.lane-play').forEach(btn => {
btn.addEventListener('click', () => {
const which = btn.dataset.lane;
if (which === 'ctor') playLane('laneCtor', 'ctorFill', 'ctorOut');
else playLane('laneFactory', 'factFill', 'factOut');
});
});
})();
</script>✅ Constructor vs Factory Function
Constructor Function | Factory Function |
|---|---|
Uses | No |
Uses | No |
Auto returns object | Must return object manually |
Methods often in prototype (.prototype) | Methods defined inside function |