Free tutorials & notes in Hindi & English · Clean code examples 🧰 मुफ़्त PDF और फ़ोटो टूल्स →
⚡ Days 15–22 – Advanced और Async JavaScript  ·  दिन 17

दिन 17: this, Classes और Object-Oriented JS

⏱ 100 min📶 Intermediate🎯 100% self-study
दिन 17 / 30

✅ आज आप सीखेंगे

  • this के चार नियम
  • call, apply और bind
  • Classes: constructor, methods, getters/setters
  • static members और private # fields
  • extends/super से inheritance – और composition कब बेहतर

🏢 असली दुनिया में

Cart logic अब product page, cart page और checkout page तीनों पर चाहिए। Functions copy करने से तीन थोड़े अलग carts बनते हैं। Cart class एक blueprint देती है: हर page एक जैसे methods और नियमों वाला cart object बनाता है, और उसका अंदरूनी हिस्सा private रहता है ताकि कोई page ग़लती से totals न बिगाड़ सके।

this के चार नियम

JavaScript
'use strict';
const shop = {
  name: 'Sharma Sweets',
  greet() { return `Welcome to ${this.name}`; },      // 1. method call → this = the object before the dot
  later() { return [1].map(() => this.name)[0]; },    // 2. arrow → this from the surrounding method
};
console.log(shop.greet());
console.log(shop.later());

const loose = shop.greet;                             // 3. plain call → this is undefined (strict mode)
try { loose(); } catch (e) { console.log('Lost this:', e.message); }

const bound = shop.greet.bind(shop);                  // 4. bind/call/apply set this explicitly
console.log(bound());
console.log(shop.greet.call({ name: 'Gupta Bakery' }));
Welcome to Sharma Sweets Sharma Sweets Lost this: Cannot read properties of undefined (reading 'name') Welcome to Sharma Sweets Welcome to Gupta Bakery
Function कैसे बुलाया गयाthis है…
obj.method()obj
साधारण fn() (strict / modules / classes)undefined
Arrow functionजहाँ arrow लिखा वहाँ का this
fn.call(x) / fn.apply(x) / fn.bind(x)x
new Fn() / new Class()नया object
Regular function वाला event listenerElement (event.currentTarget)
💡 आसान नियम

Object/class methods के लिए method shorthand, और उनके अंदर callbacks के लिए arrow functions लें – तब this लगभग हमेशा वही होता है जो आप सोचते हैं।

Classes: objects के blueprints

JavaScript
class Product {
  constructor(id, name, price, stock = 0) {   // runs on new Product(...)
    this.id = id;
    this.name = name;
    this.price = price;
    this.stock = stock;
  }
  get inStock() { return this.stock > 0; }   // getter – used like a property
  priceFor(kg) { return Math.round(this.price * kg); }
  toString() { return `${this.name} (₹${this.price}/kg)`; }
}

const kaju = new Product(1, 'Kaju Katli', 900, 25);
const kalakand = new Product(5, 'Kalakand', 600);
console.log(String(kaju), kaju.priceFor(1.5), kaju.inStock);
console.log(`${kalakand}`, kalakand.inStock);
console.log(typeof Product, kaju instanceof Product);
Kaju Katli (₹900/kg) 1350 true Kalakand (₹600/kg) false function true

असली Cart class: static और private fields

JavaScript
class Cart {
  #items = new Map();                 // private field: id → { product, qty }
  static FREE_DELIVERY = 1500;
  static DELIVERY_CHARGE = 60;

  add(product, qty = 1) {
    if (qty <= 0) throw new Error('Quantity must be positive');
    const line = this.#items.get(product.id);
    this.#items.set(product.id, { product, qty: (line?.qty ?? 0) + qty });
    return this;                       // allows chaining: cart.add(a).add(b)
  }
  remove(id) { this.#items.delete(id); return this; }
  get count() { return [...this.#items.values()].reduce((n, l) => n + l.qty, 0); }
  get subtotal() { return [...this.#items.values()].reduce((s, l) => s + l.product.price * l.qty, 0); }
  get delivery() { return this.subtotal === 0 || this.subtotal >= Cart.FREE_DELIVERY ? 0 : Cart.DELIVERY_CHARGE; }
  get total() { return this.subtotal + this.delivery; }
  lines() { return [...this.#items.values()].map(l => `${l.product.name} × ${l.qty} = ₹${l.product.price * l.qty}`); }
}

const cart = new Cart();
cart.add({ id: 1, name: 'Kaju Katli', price: 900 }, 1)
    .add({ id: 4, name: 'Besan Ladoo', price: 500 })
    .add({ id: 1, name: 'Kaju Katli', price: 900 }, 0.5);
console.log(cart.lines().join('\n'));
console.log(`Items ${cart.count} · subtotal ₹${cart.subtotal} · delivery ₹${cart.delivery} · total ₹${cart.total}`);
console.log(cart.items, Object.keys(cart));          // #items is truly private
try { cart.add({ id: 9, name: 'X', price: 1 }, 0); } catch (e) { console.log('Error:', e.message); }
Kaju Katli × 1.5 = ₹1350 Besan Ladoo × 1 = ₹500 Items 2.5 · subtotal ₹1850 · delivery ₹0 · total ₹1850 undefined [] Error: Quantity must be positive
FeatureSyntaxक्यों
Private field#items = new Map()बाहर से पढ़ा या बदला नहीं जा सकता – totals सुरक्षित
Getterget total() { … }हमेशा गणना, कभी पुराना नहीं
Staticstatic FREE_DELIVERY = 1500Class पर साझा setting, हर cart पर नहीं
Return thisadd() { …; return this; }Chaining: cart.add(a).add(b)
throwthrow new Error(…)ग़लत input को साफ़ मना करना (Day 18)

extends और super से inheritance

JavaScript
class Product {
  constructor(name, price) { this.name = name; this.price = price; }
  label() { return `${this.name} – ₹${this.price}`; }
}
class GiftBox extends Product {
  constructor(name, price, contents) {
    super(name, price);                 // call the parent constructor FIRST
    this.contents = contents;
  }
  label() {                             // override, but reuse the parent version
    return `${super.label()} 🎁 (${this.contents.join(', ')})`;
  }
}
const box = new GiftBox('Assorted Box', 720, ['Kaju Katli', 'Ladoo', 'Soan Papdi']);
console.log(box.label());
console.log(box instanceof GiftBox, box instanceof Product);
Assorted Box – ₹720 🎁 (Kaju Katli, Ladoo, Soan Papdi) true true

गहरी inheritance

  • Product → Sweet → MilkSweet → BengaliMilkSweet
  • ऊपर का बदलाव कई children तोड़ता है
  • “Sugar-free gift box” दर्शाना मुश्किल

Composition ⭐

  • Product के पास tags, discount, packaging HAI
  • छोटे objects/functions जोड़ें
  • Flexible – React यही शैली पसंद करता है

असली task: UI में Cart class

HTML + JavaScript
<div id="menu"></div>
<pre id="summary" style="background:#fefce8;padding:10px;border-radius:8px"></pre>

<script>
class Cart {
  #items = new Map();                 // private field: id → { product, qty }
  static FREE_DELIVERY = 1500;
  static DELIVERY_CHARGE = 60;

  add(product, qty = 1) {
    if (qty <= 0) throw new Error('Quantity must be positive');
    const line = this.#items.get(product.id);
    this.#items.set(product.id, { product, qty: (line?.qty ?? 0) + qty });
    return this;                       // allows chaining: cart.add(a).add(b)
  }
  remove(id) { this.#items.delete(id); return this; }
  get count() { return [...this.#items.values()].reduce((n, l) => n + l.qty, 0); }
  get subtotal() { return [...this.#items.values()].reduce((s, l) => s + l.product.price * l.qty, 0); }
  get delivery() { return this.subtotal === 0 || this.subtotal >= Cart.FREE_DELIVERY ? 0 : Cart.DELIVERY_CHARGE; }
  get total() { return this.subtotal + this.delivery; }
  lines() { return [...this.#items.values()].map(l => `${l.product.name} × ${l.qty} = ₹${l.product.price * l.qty}`); }
}

const products = [
  { id: 1, name: 'Kaju Katli', price: 900 },
  { id: 2, name: 'Malai Ghewar', price: 650 },
  { id: 4, name: 'Besan Ladoo', price: 500 },
];
const cart = new Cart();
const menu = document.querySelector('#menu');
for (const p of products) {
  const btn = document.createElement('button');
  btn.textContent = `+ ${p.name} (₹${p.price})`;
  btn.addEventListener('click', () => { cart.add(p, 0.5); show(); });
  menu.append(btn, ' ');
}
function show() {
  document.querySelector('#summary').textContent = cart.count
    ? cart.lines().join('\n') + `\n\nSubtotal ₹${cart.subtotal}\nDelivery ₹${cart.delivery}\nTotal ₹${cart.total}`
    : 'Cart is empty – add ½ kg of anything';
}
show();
</script>
▶  The UI only calls add() and reads getters – rules live inside the class

🏅 आज के Job Skills

✔ Methods, arrows, events और bind में this का अनुमान✔ Constructors, methods और getters वाली classes✔ Private # fields से data सुरक्षित; static से settings साझा✔ Classes extend करना और बेहतर हो तो composition

Practice tasks

🏋️ Practice – ख़ुद करें

Task 1: Private #balance, deposit(), overdraft मना करने वाला withdraw() और getter balance वाली BankAccount class बनाएँ।
Solution देखें
JavaScript
class BankAccount {
  #balance = 0;
  constructor(owner) { this.owner = owner; }
  deposit(amount) { if (amount <= 0) throw new Error('Invalid amount'); this.#balance += amount; return this; }
  withdraw(amount) {
    if (amount > this.#balance) return `Declined: balance ₹${this.#balance}`;
    this.#balance -= amount;
    return `Withdrew ₹${amount}`;
  }
  get balance() { return this.#balance; }
}
const acc = new BankAccount('Riya').deposit(5000);
console.log(acc.withdraw(1200), '|', acc.withdraw(9000), '|', acc.balance);
Withdrew ₹1200 | Declined: balance ₹3800 | 3800
Task 2: Marks और getter percentage वाली Student class बनाएँ; उसे bonus जोड़ने वाली ScholarshipStudent में extend करें।
Task 3: यह bug ठीक करें: button.addEventListener("click", cart.clear) – clear() के अंदर this cart नहीं है।

Quick quiz

🧠 Quick Quiz – ख़ुद को जाँचें

1. obj.method() में this है…
Dot से पहले का object।
2. Arrow functions this कहाँ से लेते हैं?
Lexical this।
3. Private class field शुरू होता है…
असली privacy।
4. Child constructor में बुलाना ज़रूरी…
this से पहले।
5. static properties किसकी होती हैं?
Cart.FREE_DELIVERY।

Interview corner

💼 Interview Corner

JavaScript में this कैसे काम करता है?

this इस पर निर्भर है कि function कैसे बुलाया गया: method call → object; साधारण call → strict mode में undefined; new → नया instance; call/apply/bind → दी गई value; arrow functions का अपना this नहीं, वे बाहरी this लेते हैं।

क्या JavaScript classes असली classes हैं?

ये prototypes के ऊपर syntax हैं: methods Class.prototype पर रहते हैं और objects उससे जुड़ते हैं। Classes private # fields, static blocks और सख़्त नियम (हमेशा strict mode, new ज़रूरी) जैसी सुविधाएँ जोड़ती हैं।

सारांश

  • this call पर निर्भर: method, साधारण, new, bind, arrow।
  • class + constructor + methods + getters असली चीज़ें दर्शाते हैं।
  • #private fields data बचाते हैं; static साझा settings रखता है।
  • असली “is-a” के लिए extends/super; वरना composition।
➡️ आगे

Day 18: errors और debugging – try…catch, custom errors और DevTools breakpoints से bugs ढूँढना।

अक्सर पूछे जाने वाले प्रश्न (FAQ)

क्या React के लिए classes चाहिए?
आधुनिक React function components और hooks इस्तेमाल करता है, तो वहाँ classes कम हैं – पर OOP सोच और this interviews में पूछे जाते हैं और कई libraries में इस्तेमाल होते हैं।
_private और #private में क्या फ़र्क?
_name सिर्फ़ नाम की परंपरा है – कोई भी पढ़ सकता है। #name भाषा लागू करती है।
← JavaScript (30 Days)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

अगला topicदिन 18: Errors, try…catch और Debugging आपकी प्रगति: 17 / 30 (57%) · Lesson 18 / 30 आगे बढ़ें →

यह lesson कैसा लगा?

आपकी राय से हम content और बेहतर बनाते हैं।

अपना review और सुझाव लिखें (वैकल्पिक)

Review approve होने के बाद आपका नाम और शहर इसके साथ public दिख सकते हैं। Email या phone न लिखें।

▶ CodingEasily on YouTube

Video से सीखें – आसान Hindi में

चुनी हुई video: RDBMS भाग 3 – Class XI Commerce IT

▶ Channel subscribe करें