⚡️ Static Methods and Properties
Static members belong to the class itself, not to its objects.
Called using the class name
Cannot be accessed through instances
✅ Static Method (static)
Used for utility/helper functions
Does not need an object to run
Cannot access instance properties directly
Example:
class MathUtil {
static add(a, b) {
return a + b;
}
}
console.log(MathUtil.add(5, 3)); // 8❌ Invalid:
const m = new MathUtil();
m.add(5, 3); // Error: not a function✅ Static Properties
Store shared data for all objects
Accessed using the class name
Example:
class Counter {
static count = 0;
constructor() {
Counter.count++;
}
}
new Counter();
new Counter();
console.log(Counter.count); // 2✔ Every instance updates the same shared value
<div class="infographic-jsstatic">
<style>
.infographic-jsstatic {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--line: #ddd6c9;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--ok: #1a7f4e;
--ok-soft: #e3f5ec;
--bad: #b42318;
--bad-soft: #fbe9e7;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', -apple-system, sans-serif;
--mono-font: 'IBM Plex Mono', 'Courier New', monospace;
margin: 0 auto;
box-sizing: border-box;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-jsstatic[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--line: #2c313d;
--accent: #5b8def;
--accent-soft:#202942;
--ok: #5cd6a0;
--ok-soft: #16342a;
--bad: #e57373;
--bad-soft: #3a2222;
}
.infographic-jsstatic * { box-sizing: border-box; }
.infographic-jsstatic .ig-inner { padding: 1.75rem clamp(1.25rem, 5vw, 3rem) 2rem; }
.infographic-jsstatic .ig-title {
font-family: var(--display-font); font-size: clamp(1.4rem, 4.5vw, 1.9rem);
font-weight: 600; text-align: center; margin: 0 0 1.75rem;
}
.infographic-jsstatic .section-label {
font-family: var(--mono-font); font-size: 0.8rem; font-weight: 700; color: var(--ink);
background: var(--paper-alt); border: 1px solid var(--line); border-radius: 6px;
padding: 0.4rem 0.8rem; text-align: center; margin: 2.25rem 0 1rem;
}
.infographic-jsstatic .section-label:first-of-type { margin-top: 0; }
.infographic-jsstatic .code-block {
font-family: var(--mono-font); font-size: 0.8rem; line-height: 1.7;
background: #1e1e1e; color: #d4d4d4; border-radius: 6px;
padding: 0.8rem 1rem; white-space: pre; margin-bottom: 1.1rem;
box-shadow: 0 6px 16px rgba(0,0,0,0.2);
}
.infographic-jsstatic .code-block .kw { color: #569cd6; font-weight: 700; }
.infographic-jsstatic .code-block .stat { color: #4ec9b0; font-weight: 700; }
.infographic-jsstatic .code-block .comment { color: #6a9955; }
.infographic-jsstatic .btn-stack { display: flex; flex-direction: column; gap: 0.6rem; align-items: center; margin-bottom: 0.9rem; }
.infographic-jsstatic .try-btn {
font: inherit; font-family: var(--mono-font); font-size: 0.82rem; font-weight: 700; border: 2px solid;
padding: 0.55rem 1rem; border-radius: 8px; cursor: pointer; width: 100%; max-width: 320px; text-align: center;
background: var(--paper);
}
.infographic-jsstatic .try-btn.good { border-color: var(--ok); color: var(--ok); }
.infographic-jsstatic .try-btn.good:hover { background: var(--ok-soft); }
.infographic-jsstatic .try-btn.bad { border-color: var(--bad); color: var(--bad); }
.infographic-jsstatic .try-btn.bad:hover { background: var(--bad-soft); }
.infographic-jsstatic .outcome {
border-radius: 6px; padding: 0.7rem 0.9rem; font-family: var(--mono-font); font-size: 0.82rem;
text-align: center; min-height: 1.3em; border: 1px solid var(--line); background: var(--paper-alt); color: var(--ink-soft);
}
.infographic-jsstatic .outcome.ok-tone { border-color: var(--ok); background: var(--ok-soft); color: var(--ok); font-weight: 700; }
.infographic-jsstatic .outcome.bad-tone { border-color: var(--bad); background: var(--bad-soft); color: var(--bad); font-weight: 700; }
.infographic-jsstatic .outcome .why { display: block; margin-top: 0.3rem; font-size: 0.74rem; font-weight: 400; color: var(--ink-soft); }
/* Counter section */
.infographic-jsstatic .counter-box {
text-align: center; font-family: var(--mono-font); font-weight: 700; font-size: 1.05rem;
border: 2px solid var(--accent); background: var(--accent-soft); color: var(--accent);
border-radius: 10px; padding: 0.8rem; margin-bottom: 1rem; transition: transform 0.2s ease;
}
.infographic-jsstatic .counter-box.pulse { animation: static-pulse 0.35s ease; }
@keyframes static-pulse { 0% { transform: scale(1); } 50% { transform: scale(1.06); } 100% { transform: scale(1); } }
.infographic-jsstatic .counter-sub { text-align: center; font-size: 0.72rem; color: var(--ink-soft); margin: -0.7rem 0 1rem; }
.infographic-jsstatic .instance-row { display: flex; gap: 0.4rem; justify-content: center; flex-wrap: wrap; min-height: 2rem; margin-bottom: 1rem; }
.infographic-jsstatic .inst-chip {
font-family: var(--mono-font); font-size: 0.7rem; font-weight: 700; padding: 0.25rem 0.5rem; border-radius: 5px;
border: 1px solid var(--ok); color: var(--ok); background: var(--ok-soft);
opacity: 0; transform: scale(0.6); transition: opacity 0.3s ease, transform 0.3s ease;
}
.infographic-jsstatic .inst-chip.is-in { opacity: 1; transform: scale(1); }
.infographic-jsstatic .center-row { display: flex; justify-content: center; gap: 0.5rem; margin-bottom: 0.8rem; }
.infographic-jsstatic .act-btn {
font: inherit; font-family: var(--mono-font); font-size: 0.78rem; font-weight: 700; border: none;
color: #fff; padding: 0.55rem 0.9rem; border-radius: 999px; cursor: pointer; white-space: nowrap;
}
.infographic-jsstatic .act-btn.good { background: var(--ok); }
.infographic-jsstatic .act-btn.bad { background: var(--bad); }
.infographic-jsstatic .act-btn:hover { opacity: 0.88; }
.infographic-jsstatic .caption {
text-align: center; font-size: 0.8rem; color: var(--ink-soft);
}
.infographic-jsstatic .caption strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-jsstatic *, .infographic-jsstatic *::before, .infographic-jsstatic *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="ig-inner">
<h2 class="ig-title">Static Methods & Properties</h2>
<div class="section-label">1. Static Method — belongs to the class</div>
<div class="code-block"><span class="kw">class</span> MathUtil {
<span class="stat">static</span> add(a, b) {
<span class="kw">return</span> a + b;
}
}
<span class="comment">// an instance, for comparison</span>
<span class="kw">const</span> m = <span class="kw">new</span> MathUtil();</div>
<div class="btn-stack">
<button class="try-btn good" id="classCallBtn">Run: MathUtil.add(5, 3)</button>
<button class="try-btn bad" id="instCallBtn">Run: m.add(5, 3)</button>
</div>
<div class="outcome" id="methodResult">click a line above to run it</div>
<div class="section-label">2. Static Property — shared by every instance</div>
<div class="code-block"><span class="kw">class</span> Counter {
<span class="stat">static</span> count = 0;
constructor() {
Counter.count++;
}
}</div>
<div class="counter-box" id="counterBox">Counter.count = 0</div>
<div class="counter-sub">one shared value — not copied per instance</div>
<div class="instance-row" id="instanceRow"></div>
<div class="center-row">
<button class="act-btn good" id="newInstanceBtn">Run: new Counter()</button>
<button class="act-btn bad" id="resetCounterBtn">⟲ Reset</button>
</div>
<p class="caption" id="counterCaption">click "new Counter()" a few times and watch the count</p>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-jsstatic')
|| document.querySelector('.infographic-jsstatic');
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');
// Static method demo
const classCallBtn = wrapper.querySelector('#classCallBtn');
const instCallBtn = wrapper.querySelector('#instCallBtn');
const methodResult = wrapper.querySelector('#methodResult');
classCallBtn.addEventListener('click', () => {
methodResult.className = 'outcome ok-tone';
methodResult.innerHTML = `MathUtil.add(5, 3) → 8<span class="why">called on the class — this is where static methods live</span>`;
});
instCallBtn.addEventListener('click', () => {
methodResult.className = 'outcome bad-tone';
methodResult.innerHTML = `TypeError: m.add is not a function<span class="why">m is an instance — static methods aren't copied onto instances</span>`;
});
// Static property demo
const counterBox = wrapper.querySelector('#counterBox');
const instanceRow = wrapper.querySelector('#instanceRow');
const newInstanceBtn = wrapper.querySelector('#newInstanceBtn');
const resetCounterBtn = wrapper.querySelector('#resetCounterBtn');
const counterCaption = wrapper.querySelector('#counterCaption');
let count = 0;
newInstanceBtn.addEventListener('click', () => {
count++;
counterBox.textContent = `Counter.count = ${count}`;
counterBox.classList.add('pulse');
setTimeout(() => counterBox.classList.remove('pulse'), 350);
const chip = document.createElement('span');
chip.className = 'inst-chip';
chip.textContent = `instance ${count}`;
instanceRow.appendChild(chip);
requestAnimationFrame(() => chip.classList.add('is-in'));
counterCaption.innerHTML = `<strong>${count}</strong> instance${count > 1 ? 's' : ''} created, and each one incremented the <strong>same</strong> Counter.count`;
});
resetCounterBtn.addEventListener('click', () => {
count = 0;
counterBox.textContent = 'Counter.count = 0';
instanceRow.innerHTML = '';
counterCaption.textContent = 'click "new Counter()" a few times and watch the count';
});
})();
</script>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});💵 Example: BankAccount with Static Interest Rate & Account Counter
class BankAccount {
static interestRate = 0.05; // ✅ static property (shared by all accounts)
static totalAccounts = 0; // ✅ tracks how many accounts are created
constructor(owner, balance) {
this.owner = owner;
this.balance = balance;
BankAccount.totalAccounts++; // ✅ updates shared static value
}
addInterest() {
this.balance += this.balance * BankAccount.interestRate;
return this.balance;
}
static setInterestRate(newRate) { // ✅ static method
BankAccount.interestRate = newRate;
}
static getTotalAccounts() { // ✅ static method
return BankAccount.totalAccounts;
}
}
// --- Usage ---
const acc1 = new BankAccount("Bhaskar", 1000);
const acc2 = new BankAccount("Tisha", 2000);
console.log(BankAccount.getTotalAccounts()); // 2 ✅
acc1.addInterest();
console.log(acc1.balance); // 1050 ✅ (5% added)
BankAccount.setInterestRate(0.10); // ✅ update shared rate
acc2.addInterest();
console.log(acc2.balance); // 2200 ✅ (10% added)✅ Static vs Instance
Feature | Static | Instance |
|---|---|---|
Belongs to | Class | Object |
Accessed by |
|
|
Shared across instances | ✅ Yes | ❌ No |
Needs object to use | ❌ No | ✅ Yes |