Getter (get)
Used to read a property
Looks like a normal property but runs a function behind the scenes
Setter (set)
Used to update a property
Allows validation, logic, or formatting before assigning
✅ Basic Example
class Person {
constructor(name) {
this._name = name; // underscore means "internal property"
}
get name() {
return this._name.toUpperCase();
}
set name(value) {
this._name = value.trim();
}
}
const p = new Person("Raman");
console.log(p.name);
// Raman (getter called)
p.name = " Sharma "; // setter called
console.log(p.name);
// Sharma (getter called)🔍 What’s happening?
p.name→ calls getterp.name = " Saha "→ calls setterInternally stored in
_name
✅ Why use Getters and Setters?
✔ Add validation
set age(value) {
if (value < 0) throw new Error("Age cannot be negative");
this._age = value;
}✔ Compute values dynamically
get fullName() {
return `${this.first} ${this.last}`;
}✔ Control how data is accessed and modified
✔ Keep internal data protected
✅ Using Getters/Setters Without Underscore?
Technically possible — but dangerous:
set name(value) {
this.name = value; // ❌ infinite recursion
}It keeps calling itself forever.
Always store internally using a different name (like _name).
✅ Class Property Access Looks Like Normal Variable
p.name // NOT a function call
p.name() // ❌ incorrectGetters make methods feel like properties — cleaner API.
<div class="infographic-gscode">
<style>
.infographic-gscode {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--line: #ddd6c9;
--accent: #2563eb;
--mono-font: 'IBM Plex Mono', 'Courier New', 'Consolas', monospace;
--body-font: 'Inter', -apple-system, sans-serif;
margin: 0 auto;
box-sizing: border-box;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-gscode[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--line: #2c313d;
--accent: #5b8def;
}
.infographic-gscode * { box-sizing: border-box; }
.infographic-gscode .ig-inner { padding: 0; }
.infographic-gscode .vscode {
background: #1e1e1e; border-radius: 8px; overflow: hidden;
box-shadow: 0 8px 20px rgba(0,0,0,0.25); font-family: var(--mono-font);
}
.infographic-gscode .vs-tabbar { display: flex; background: #252526; }
.infographic-gscode .vs-tab {
display: flex; align-items: center; gap: 0.45rem; padding: 0.55rem 1rem;
background: #1e1e1e; border-top: 2px solid #007acc; font-size: 0.78rem; color: #d4d4d4;
}
.infographic-gscode .vs-tab .dot { width: 0.55rem; height: 0.55rem; border-radius: 50%; background: #3178c6; }
.infographic-gscode .vs-body { display: flex; padding: 0.9rem 0; }
.infographic-gscode .vs-gutter {
display: flex; flex-direction: column; padding: 0 0.7rem; color: #6e7681; font-size: 0.78rem;
line-height: 1.5; text-align: right; user-select: none;
}
.infographic-gscode .vs-code {
padding: 0 1rem 0 0.4rem; font-size: 0.78rem; line-height: 1.5; color: #d4d4d4; white-space: pre;
}
.infographic-gscode .kw { color: #569cd6; }
.infographic-gscode .type { color: #4ec9b0; }
.infographic-gscode .var { color: #9cdcfe; }
.infographic-gscode .method { color: #dcdcaa; }
.infographic-gscode .num { color: #b5cea8; }
.infographic-gscode .str { color: #ce9178; }
.infographic-gscode .comment { color: #6a9955; }
.infographic-gscode .punc { color: #d4d4d4; }
.infographic-gscode .exec-line { display: block; border-radius: 4px; padding: 0 0.3rem; margin: 0 -0.3rem; transition: background 0.3s ease; }
.infographic-gscode .exec-line.is-active { background: #2d3f5e; }
.infographic-gscode .exec-line.is-error { background: #4a1f1f; }
.infographic-gscode .call-row { display: flex; justify-content: center; gap: 0.5rem; margin-top: 1.25rem; }
.infographic-gscode .call-btn {
font: inherit; font-family: var(--mono-font); font-size: 0.85rem; font-weight: 700; border: none;
background: #007acc; color: #fff; padding: 0.55rem 1.2rem; border-radius: 999px; cursor: pointer;
}
.infographic-gscode .call-btn:hover:not(:disabled) { opacity: 0.9; }
.infographic-gscode .call-btn:disabled { opacity: 0.5; cursor: default; }
.infographic-gscode .call-btn.ghost { background: transparent; border: 1px solid var(--line); color: var(--ink-soft); }
.infographic-gscode .terminal {
margin-top: 1.1rem; background: #1e1e1e; border-radius: 8px; overflow: hidden;
box-shadow: 0 8px 20px rgba(0,0,0,0.25);
}
.infographic-gscode .term-bar { display: flex; gap: 0.4rem; padding: 0.55rem 0.7rem; background: #2d2d2d; }
.infographic-gscode .term-dot { width: 0.65rem; height: 0.65rem; border-radius: 50%; }
.infographic-gscode .term-dot.red { background: #ff5f56; }
.infographic-gscode .term-dot.yellow { background: #ffbd2e; }
.infographic-gscode .term-dot.green { background: #27c93f; }
.infographic-gscode .term-body {
font-family: var(--mono-font); font-size: 0.85rem; padding: 0.9rem 1rem; min-height: 3.5rem; color: #d4d4d4; line-height: 1.6;
}
.infographic-gscode .term-line { opacity: 0; transform: translateY(4px); transition: opacity 0.25s ease, transform 0.25s ease; }
.infographic-gscode .term-line.is-in { opacity: 1; transform: translateY(0); }
.infographic-gscode .term-prompt { color: #6a9955; }
.infographic-gscode .term-output { color: #6bcf7f; font-weight: 700; }
.infographic-gscode .term-output.is-error { color: #ff6b6b; }
</style>
<div class="ig-inner">
<div class="vscode">
<div class="vs-tabbar"><div class="vs-tab"><span class="dot"></span>Person.ts</div></div>
<div class="vs-body">
<div class="vs-gutter" id="gutter"></div>
<div class="vs-code"><span class="exec-line"><span class="kw">class</span> Person {</span><span class="exec-line"> <span class="kw">private</span> _age: <span class="type">number</span>;</span><span class="exec-line"> constructor(age: <span class="type">number</span>) {</span><span class="exec-line"> <span class="kw">this</span>._age = age;</span><span class="exec-line"> }</span><span class="exec-line"> <span class="kw">get</span> age(): <span class="type">number</span> {</span><span class="exec-line"> <span class="kw">return</span> <span class="kw">this</span>._age;</span><span class="exec-line"> }</span><span class="exec-line"> <span class="kw">set</span> age(value: <span class="type">number</span>) {</span><span class="exec-line"> <span class="kw">if</span> (value < <span class="num">0</span>) {</span><span class="exec-line"> <span class="kw">throw</span> <span class="kw">new</span> <span class="method">Error</span>(<span class="str">"Age cannot be negative"</span>);</span><span class="exec-line"> }</span><span class="exec-line"> <span class="kw">this</span>._age = value;</span><span class="exec-line"> }</span><span class="exec-line">}</span><span class="exec-line" id="line-new"><span class="kw">const</span> p = <span class="kw">new</span> <span class="method">Person</span>(<span class="num">25</span>);</span><span class="exec-line" id="line-get1"><span class="var">console</span>.<span class="method">log</span>(p.age); <span class="comment">// Uses getter</span></span><span class="exec-line" id="line-set"><span class="punc">p</span>.age = <span class="num">30</span>; <span class="comment">// Uses setter</span></span><span class="exec-line" id="line-get2"><span class="var">console</span>.<span class="method">log</span>(p.age); <span class="comment">// 30</span></span><span class="exec-line" id="line-bad"><span class="comment">// p.age = -5; // Error</span></span></div>
</div>
</div>
<div class="call-row">
<button class="call-btn" id="playBtn">▶ Run</button>
<button class="call-btn ghost" id="restartBtn">⟲ Restart</button>
</div>
<div class="terminal">
<div class="term-bar"><span class="term-dot red"></span><span class="term-dot yellow"></span><span class="term-dot green"></span></div>
<div class="term-body" id="termBody"></div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-gscode')
|| document.querySelector('.infographic-gscode');
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');
const gutter = wrapper.querySelector('#gutter');
const codeEl = wrapper.querySelector('.vs-code');
const totalLines = codeEl.querySelectorAll('.exec-line').length;
for (let i = 1; i <= totalLines; i++) {
const n = document.createElement('span');
n.textContent = i;
gutter.appendChild(n);
}
const playBtn = wrapper.querySelector('#playBtn');
const restartBtn = wrapper.querySelector('#restartBtn');
const termBody = wrapper.querySelector('#termBody');
const lineNew = wrapper.querySelector('#line-new');
const lineGet1 = wrapper.querySelector('#line-get1');
const lineSet = wrapper.querySelector('#line-set');
const lineGet2 = wrapper.querySelector('#line-get2');
const lineBad = wrapper.querySelector('#line-bad');
const allExecLines = [lineNew, lineGet1, lineSet, lineGet2, lineBad];
const STEPS = [
{ line: lineNew, log: null },
{ line: lineGet1, log: '25' },
{ line: lineSet, log: null },
{ line: lineGet2, log: '30' },
{ line: lineBad, log: 'Uncaught Error: Age cannot be negative', isError: true }
];
let timer = null;
let idx = -1;
function resetVisual() {
allExecLines.forEach(l => { l.classList.remove('is-active', 'is-error'); });
termBody.innerHTML = '';
}
function addTermLine(text, isError) {
const line = document.createElement('div');
line.className = 'term-line';
line.innerHTML = isError
? `<span class="term-output is-error">${text}</span>`
: `<span class="term-prompt">></span> <span class="term-output">${text}</span>`;
termBody.appendChild(line);
requestAnimationFrame(() => line.classList.add('is-in'));
}
function applyStep(step) {
allExecLines.forEach(l => l.classList.remove('is-active', 'is-error'));
step.line.classList.add(step.isError ? 'is-error' : 'is-active');
if (step.log) addTermLine(step.log, step.isError);
}
function stop() {
clearInterval(timer);
timer = null;
playBtn.textContent = '▶ Run';
}
function advance() {
idx++;
if (idx >= STEPS.length) { stop(); return; }
applyStep(STEPS[idx]);
if (idx >= STEPS.length - 1) stop();
}
function play() {
if (timer) { stop(); return; }
if (idx >= STEPS.length - 1) restart(false);
playBtn.textContent = '⏸ Pause';
timer = setInterval(advance, 900);
advance();
}
function restart() {
stop();
idx = -1;
resetVisual();
}
playBtn.addEventListener('click', play);
restartBtn.addEventListener('click', restart);
restart();
})();
</script>✅ Quick Summary
Feature | Purpose |
|---|---|
| Reads a value with logic behind it |
| Writes a value with validation or formatting |
Looks like property | No parentheses needed |
Use internal field | Avoid recursion (e.g., |