Skip to content

Latest commit

 

History

History
600 lines (413 loc) · 54.2 KB

README_bn-BD.md

File metadata and controls

600 lines (413 loc) · 54.2 KB

শিখুন-ভুলুন-আবার শিখুন জাভাস্ক্রিপ্ট 🔄

আপনি কতটুকু জাভাস্ক্রিপ্ট জানেন পরীক্ষা করুন, আপনার জ্ঞানকে একটু ঝালাই করে নিন অথবা আপনার ইন্টার্ভিউর জন্য প্রস্তুতি নিন 💪। আপনার সুবিধামত শিখুন! 🎓 বিস্তারিত লেখা কল্যাপ্সড আকারে আছে, দেখার জন্য ক্লিক করুন 🔽। অবসরে আনন্দের জন্য আমি এটা লিখেছি, ভুল ত্রুটি মার্জনা করবেন। আপনি উপকৃত হলে, রিপোজিটোরিকে ⭐️ বা কোথাও একটি রেফারেন্স দিতে পারেন আমার খুব ভালো লাগবে।
আপনার প্রোগ্রামিং যাত্রার জন্য শুভকামনা ! 🙏 হ্যাপি কোডিং! 🧑‍💻

💬 যদি আমার সাথে যোগাযোগ করতে চান, ↩️
Facebook | LinkedIn | Blog



1. 🧐 আসুন বুঝি জাভাস্ক্রিপ্টের truthyfalsy ভ্যালুগুলো

ক্লিক করে বিস্তারিত দেখুন

✅ প্রিমিটিভ টাইপগুলো

  • 💡 এগুলো একক, অপরিবর্তনীয় ভ্যালুগুলির প্রতিনিধিত্ব করে। জাভাস্ক্রিপ্টের প্রিমিটিভ টাইপগুলো মধ্যে রয়েছে undefinednullbooleannumberstringsymbol, ও BigInt

  • 💡 যদি প্রিমিটিভ টাইপের একটি ভ্যালু থাকে যা মিথ্যা বলে বিবেচিত হয় (যেমন 0false""nullundefined, বা NaN), তবে এটি বুলিয়ান কনট্যাক্সে মিথ্যা হিসাবে আচরণ করবে।

  • 💡 এগুলি সরাসরি মেমরিত সেই অবস্থানে সংরক্ষণ করা হয় যেখানে ভেরিয়েবল তাদের অ্যাক্সেস করে৷

✅ রেফারেন্স টাইপগুলো

  • 💡 এখানে আবজেক্টগুলি অন্তর্ভুক্ত হয় যেমন functionarray, এবং অন্যান্য objects এবং এগুলোর ভ্যালু পরিবর্তনযোগ্য।

  • 💡 যখন আপনি একটি রেফারেন্স টাইপ তৈরি করেন, তখন জাভাস্ক্রিপ্ট এটির জন্য মেমরি বরাদ্দ করে এবং আপনি যে ভেরিয়েবলে এটিকে অ্যাসাইন করেন সেটি ঐ মেমরি স্পেসের একটি রেফারেন্স (বা পয়েন্টার) ধরে রাখে, প্রকৃত ডেটা নয়।

  • 💡 যেহেতু একটি রেফারেন্স একটি আবজেক্টকে নির্দেশ করে এবং জাভাস্ক্রিপ্টের আবজেক্টগুলি সহজাতভাবেই সত্য, তাই একটি রেফারেন্স টাইপ মিথ্যা হতে পারে না। এমনকি যদি কোনো আবজেক্টের কোন কি-ভ্যালু নাও থাকে (যেমন {}) বা কোনো অ্যারের কোনো এলিমেন্ট না থাকে ([]), তবুও এটি সত্য কারন বরাদ্দকৃত মেমরি স্পেসের একটি রেফারেন্স থাকে।

🤔 কেন ফাংশন কনস্ট্রাক্টরগুলো সত্য হয়?

  • 💡 ফাংশন কনস্ট্রাক্টর যেমন new Number() বা new Boolean() প্রিমিটিভ ভ্যালুগুলোকে ঘিরে একটি অবজেক্ট র‍্যাপার তৈরি করে।

  • 💡 অবজেক্টের অভ্যন্তরে প্রিমিটিভ ভ্যালু মিথ্যা হওয়া সত্ত্বেও (0 বা false) অবজেক্টের র‍্যাপার নিজেই একটি রেফারেন্স টাইপ।

  • 💡 যেমন আমরা উপরে জেনেছি, রেফারেন্স টাইপ সবসময়ই সত্য কারন তারা একটি মেমরি স্পেসকে রেফার/নির্দেশ করে, নিজ ভ্যালুকে নয়।

✨ সহজ-সরল উপমাঃ পেপার-ফোল্ডার

প্রিমিটিভ টাইপগুলোকে কাগজের টুকরো হিসাবে মনে করুন যাতে কিছু লেখা থাকে। যদি কাগজটি ফাঁকা হয় (একটি মিথ্যা মান), এটি কিছুই না থাকার মত বা মিথ্যা। অন্যদিকে, রেফারেন্সের টাইপগুলি ফোল্ডারের মতো (অবজেক্ট) যা এই কাগজগুলি ধরে রাখতে পারে। এমনকি ফোল্ডারটি একটি ফাঁকা কাগজ রাখার জন্য ডিজাইন করা হলেও, ফোল্ডারটি এখনও আছে এবং এটি অবশ্যই কিছু একটা (সত্য)। ফাংশন কনস্ট্রাক্টর যেমন new Number() এবং new Boolean() একটি লেবেলযুক্ত বিশেষ ফোল্ডারের মতো এবং লেবেলটিতে 0 বা false (falsy) লেখা থাকলেও ফোল্ডারটি এখনও একটি বস্তু যা আপনি রেফারেন্স এবং ব্যবহার করতে পারেন (সত্য)।

🧠 মনে রাখবেন, জাভাস্ক্রিপ্টে, ভ্যালুর টাইপ তার সত্যতা বা মিথ্যা নির্ধারণ করে। সর্বদা গ্যারান্টিযুক্ত সত্য ভ্যালুর জন্য অবজেক্টকেই আপনি প্রথম অগ্রাধিকার দিবেন!

2. 👨‍👩‍👧‍👦 আসুন বুঝি জাভাস্ক্রিপ্টের Prototypal Inheritance

ক্লিক করে বিস্তারিত দেখুন

জাভাস্ক্রিপ্টে, একটি প্রোটোটাইপ হলো অবজেক্ট তৈরির একটি ব্লুপ্রিন্টের মতো। এটি নিজেই একটি অবজেক্ট, এবং জাভাস্ক্রিপ্টের প্রতিটি ফাংশনের জন্যই একটি প্রোটোটাইপ প্রোপার্টি রয়েছে যা নতুন অবজেক্ট তৈরি করার সময় ব্যবহৃত হয়। এই প্রোটোটাইপ অবজেক্টের মধ্যে প্রয়োজনীয় প্রোপার্টি এবং মেথড গুলো রয়েছে যেন ঐ ফাংশন থেকে তৈরিকৃত অবজেক্টগুলো এদেরকে সুবিধা কাজে লাগাতে পারে।

💡 সহজ-সরল উপমা: কেক বানানোর রেসিপি

কল্পনা করুন আপনার কাছে একটি কেকের রেসিপি আছে। এই রেসিপিটিতে আপনার কেক তৈরির জন্য প্রয়োজনীয় সমস্ত পদক্ষেপগুলো এবং উপাদানগুলো অন্তর্ভুক্ত রয়েছে। জাভাস্ক্রিপ্টে, রেসিপিটি প্রোটোটাইপ-এর মতো। আপনি যখন এই রেসিপিটি ব্যবহার করে একটি কেক তৈরি করেন, তখন কেক (একটি অবজেক্ট) রেসিপি (প্রোটোটাইপ) থেকে সমস্ত প্রোপার্টিগুলো উত্তরাধিকার সূত্রে পায়। আপনি যদি রেসিপিতে একটি নতুন পদক্ষেপ যোগ করার সিদ্ধান্ত নেন, যেমন আইসিং যোগ করা, সেই রেসিপি থেকে তৈরি সমস্ত কেকগুলিতেও এখন আইসিং থাকবে।

ℹ️ একইভাবে, আপনি যখন জাভাস্ক্রিপ্টে একটি কনস্ট্রাক্টর ফাংশন থেকে একটি অবজেক্ট তৈরি করেন, তখন অবজেক্টটি কনস্ট্রাক্টরের প্রোটোটাইপ থেকে সমস্ত প্রোপার্টি এবং মেথড গুলোর উত্তরাধিকারী হয়। এটি একই কনস্ট্রাক্টর থেকে তৈরি সমস্ত বস্তুকে একই প্রোপার্টি এবং মেথড গুলো ভাগাভাগি করার অনুমতি দেয়, যা মেমরি সংরক্ষণ করতে পারে এবং একটি সামঞ্জস্যপূর্ণ কাঠামোর জন্য অনুমতি দেয়।

ℹ️ সুতরাং, প্রোটোটাইপল ইনহেরিটেন্স হল একটি উপায় যার মাধ্যমে জাভাস্ক্রিপ্টের অবজেক্টগুলি প্রোটোটাইপ থেকে প্রোপার্টি এবং মেথড গুলোর উত্তরাধিকারী হতে পারে, অনেকটা একই রেসিপি থেকে কীভাবে একাধিক কেক তৈরি করা যায়। কিন্তু যদি প্রোটোটাইপ থেকে একটি প্রোপার্টি/মেথড মুছে ফেলা হয়, সেই প্রোটোটাইপ থেকে উত্তরাধিকারসূত্রে পাওয়া সমস্ত অবজেক্ট সেই প্রোপার্টি/মেথড-এর অ্যাক্সেস হারাবে।

📝  সতর্কতার সাথে হ্যান্ডল করুন

যদিও আপনি ক্রমাগত প্রোটোটাইপগুলিতে কিছু যোগ করতে উৎসাহিত হবেন, এটিকে সাধারণত উৎসাহিত করা হয় না কারণ এটি আপনার কোডে অপ্রত্যাশিত আচরন নিয়ে আসতে পারে, বিশেষ করে যদি লাইব্রেরি বা ফ্রেমওয়ার্কগুলি ব্যবহার করা হয় তারাও প্রোটোটাইপটিকে পরিবর্তন করতে পারে। মনে রাখবেন যে মহান শক্তির সাথে মহান দায়িত্বও আসে। 🙂

🎓 এক্ষেত্রে মনে রাখতে হবে

প্রোটোটাইপল ইনহেরিটেন্স হল জাভাস্ক্রিপ্টের একটি শক্তিশালী ফিচার যার মাধ্যমে অবজেক্টের আচরণগুলিকে দক্ষতার সাথে ভাগাভাগি ও বিস্তৃত করা যায়। এটিই জাভাস্ক্রিপ্টকে ডায়নামিক এবং ফ্লেক্সিবল করে তোলে, যা আমাদের আরও পুনঃব্যবহারযোগ্য এবং রক্ষণাবেক্ষণযোগ্য কোড লিখার সক্ষমতা দেয়। 💪

✨ সুতরাং, পরের বার আপনি যখন জাভাস্ক্রিপ্টের অবজেক্টের নিয়ে কাজ করবেন, তখন প্রোটোটাইপের ফ্যামিলি ট্রি মনে রাখবেন এবং কীভাবে এটি শেয়ার করা DNA-এর সাহায্যে আপনার কোডকে শক্তিশালী করে। 🧬

🧠 এখন যেহেতু আমরা মুল জিনিসটি বুঝতে পেরেছি, আসুন নিচের উদাহরণগুলো দেখা যাক।

উদাহরনঃ Barking Dog

class Dog {
  constructor(name) {
    this.name = name;
  }
}

Dog.prototype.bark = function () {
  console.log(`Woof I am ${this.name}`);
};

const pet = new Dog("Mara");

pet.bark(); // Outputs: Woof I am Mara

ব্যাখ্যাঃ কুকুরের name অ্যাসাইন করার জন্য একটি Dog ক্লাস তৈরি করা হয়েছে একটি কনস্ট্রাক্টর সহ। Dog-এর প্রোটোটাইপে একটি মেথড bark যোগ করা হয়েছে, যেটা Dog-এর সকল ইন্সট্যান্সকে এই মেথড ব্যবহার করতে দেয়। Dog এর একটি নতুন ইন্সট্যান্স তৈরি করা হয়েছে Mara নামে, এবং pet.bark() কে কল করা হয়, যেটি Woof I am Mara কলসলে লগ করে৷

উদাহরনঃ String.prototype

// Adding a method to String.prototype
String.prototype.shout = function () {
  return this.toUpperCase() + "!!!";
};

let greeting = "hello";
console.log(greeting.shout()); // Outputs: HELLO!!!

ব্যাখ্যাঃ এখানে, আমরা String.prototype-এ shout নামে একটি মেথড যোগ করেছি। এর মানে জাভাস্ক্রিপ্টে তৈরি প্রতিটি স্ট্রিং এখন এই shout মেথডের অ্যাক্সেস পাবে। মেথডটি স্ট্রিংটিকে বড় হাতের অক্ষরে রূপান্তর করে এবং বিস্ময়বোধক চিহ্ন যোগ করে।

উদাহরনঃ Array.prototype

// Adding a method to Array.prototype
Array.prototype.firstElement = function () {
  return this.length > 0 ? this[0] : undefined;
};

let numbers = [1, 2, 3];
console.log(numbers.firstElement()); // Outputs: 1

ব্যাখ্যাঃ আমরা Array.prototype-এ firstElement নামে একটি মেথড যোগ করেছি। এই মেথডটি একটি অ্যারের প্রথম এলিমেন্ট রিটার্ন করে যদি তা অ্যারেতে থাকে। এখন, আমরা যেকোন অ্যারে তৈরি করলেই তাতে এই firstElement মেথড ব্যাবহার করতে পারব।

উদাহরনঃ Object.prototype

// Adding a method to Object.prototype
Object.prototype.keysCount = function () {
  return Object.keys(this).length;
};

let person = { name: "Alice", age: 25 };
console.log(person.keysCount()); // Outputs: 2

ব্যাখ্যাঃ আমরা Object.prototype-এ keysCount নামে একটি মেথড যোগ করেছি। এই মেথডটি একটি অবজেক্টের কী-গুলোর (প্রোপার্টিগুলোর) সংখ্যা রিটার্ন করে। এই মেথডটি Object.prototype-এ যোগ করার মাধ্যমে, জাভাস্ক্রিপ্টে তৈরি করা প্রতিটি অবজেক্টে person সহ, এখন keysCount মেথডের অ্যাক্সেস আছে। যখন আমরা person.keysCount() কল করি, তখন এটি 2 আউটপুট দেয় কারন personঅবজেক্টে দুটি কী/প্রোপার্টি আছে: name এবং age

3. 🤝 জাভাস্ক্রিপ্টে Promise-গুলো আসলে কি?

ক্লিক করে বিস্তারিত দেখুন

একটি প্রোমিস (প্রতিশ্রুতি) হল একটি বিশেষ জাভাস্ক্রিপ্ট অবজেক্ট যা "প্রোডিউসিং কোড" কে (যা একটি অ্যাসিঙ্ক্রোনাস অপারেশন সম্পাদন করে) "কনসিউমিং কোড"-এর (যা সেই অপারেশনের ফলাফল পরিচালনা করে) সাথে সংযুক্ত করে। এটিকে একটি সাবস্ক্রিপশন লিস্ট হিসাবে ভাবুন: প্রোমিস (প্রতিশ্রুতি) নিশ্চিত করে যে ফলাফলটি প্রস্তুত হলে সকল সাবস্ক্রাইবার কোডে তাকে ব্যবহার করা যাবে৷

✨ সহজ-সরল উপমা: রেস্তোরাঁয় রিজার্ভেশন

কল্পনা করুন আপনি আগামী সপ্তাহে আপনার ভাগ্না/ভাগ্নির জন্মদিনের পার্টির জন্য একটি রেস্তোরাঁয় একটি রিজার্ভেশন করছেন। আপনি যখন বুকিং করেন, তখন রেস্তোরাঁ আপনাকে প্রতিশ্রুতি দেয় যে নির্দিষ্ট সময়ে আপনার জন্য একটি টেবিল প্রস্তুত থাকবে। এই উদাহরনে:

  • 👉 প্রোডিউসিং কোড: রেস্তোরাঁর কর্মী যেমন-একজন ওয়েটার, টেবিল প্রস্তুত (প্রতিশ্রুত ফলাফল) করতে যতটা সময় লাগে নিয়েছেন।

  • 👉 প্রমিস: টেবিল রিজার্ভেশন নিজেই প্রতিশ্রুতি হিসাবে কাজ করে। এটি নিশ্চিত করে যে আপনি যখন পৌঁছাবেন তখন টেবিলটি আপনার পার্টির জন্য প্রস্তুত থাকবে।

🧩 প্রমিসের মূল ধারণা

  1. একটি প্রমিসের অবস্থাগুলো:

    • 👉 Pending/অমীমাংসিত: প্রমিস একটি রেসপন্সের জন্য অপেক্ষা করছে (যেমন টেবিল সেট করার জন্য অপেক্ষা করা)।

    • 👉 Resolved (Fulfilled)/সমাধান করা (পূর্ণ): প্রমিসটি সফলভাবে একটি ভ্যালু রিটার্ন করেছে (যেমন যখন টেবিলটি প্রস্তুত)।

    • 👉 Rejected/প্রত্যাখ্যান: প্রমিস একটি ত্রুটির সম্মুখীন হয়েছে (যেমন যখন রেস্তোরাঁটি আপনার রিজার্ভেশনের ব্যবস্থা করতে পারেনি)।

  2. জাভাস্ক্রিপ্টে একটি প্রমিস তৈরি করা:

    • 👉 আপনি Promise কনস্ট্রাক্টরটি ব্যবহার করে একটি প্রমিস তৈরি করতে পারেন। এটি দুটি প্যারামিটার সহ একটি কলব্যাক ফাংশন নেয়: resolve এবং reject

    • 👉 কলব্যাকের ভিতরে, আপনি আপনার অ্যাসিঙ্ক্রোনাস অপারেশন সম্পন্ন করবেন (যেমন, ডেটা আদান-প্রদান, একটি ইমেজ লোড করা ইত্যাদি)।

    • 👉 সবকিছু ঠিকঠাক থাকলে, আপনি ফলাফলের সাথে resolve কল করবেন। যদি কোনো ত্রুটি থাকে, তাহলে আপনি একটি এরর ম্যাসেজ দিয়ে reject কল করবেন।

🧠 মনে রাখবেন, প্রমিস আপনাকে অ্যাসিঙ্ক্রোনাস অপারেশনগুলিকে আরও মার্জিতভাবে পরিচালনা করার ফাংশনালিটি দেয়, যা আপনার কোডকে আরও পরিষ্কার করে এবং যুক্তি করা সহজ করে তোলে। যেমন রেস্তোরাঁর রিজার্ভেশনের মতো, তারা নিশ্চিত করে যে ফলাফলটি প্রয়োজনমত পাওয়া যাবে! 🍽️

🕹️ এখন যেহেতু আমরা মুল জিনিসটি বুঝতে পেরেছি, আসুন নিচের উদাহরণগুলো দেখা যাক।

উদাহরনঃ প্রমিস তৈরি ও ব্যবহার করা

// Creating a promise
const reservationPromise = new Promise((resolve, reject) => {
  // Simulating an asynchronous operation (e.g., fetching data)
  const condition = true;

  if (condition) {
    setTimeout(() => {
      const data = "Stuff worked!";
      resolve(data); // Resolve the promise;
    }, 2000); // Simulating a delay
  } else {
    setTimeout(() => {
      reject(Error("Promise is rejected.")); // Reject the promise;
    }, 2000); // Simulating a delay
  }
});

// Consuming the promise
reservationPromise
  .then((result) => {
    console.log("Promise worked!", result); // Handle success
  })
  .catch((err) => {
    console.log("Something went wrong!", err.message); // Handle error
  });

ব্যাখ্যাঃ

  • আমরা একটি প্রমিস তৈরি করেছি reservationPromise যা শর্তের ভিত্তিতে ২-সেকেন্ড পরে resolves/reject হয়।
  • যদি condition true হয়, তাহলে এটি কনসলে লগ করে Promise worked! Stuff worked!
  • যদি condition false হয়, এটা লগ করে Something went wrong! Promise is rejected. (আপনি ইচ্ছামত এরর ম্যাসেজ কাস্টমাইজ করতে পারেন)।

উদাহরনঃ Fetch API-এর সাথে async/await-এর ব্যবহার

async function getData() {
  try {
    const response = await fetch("https://jsonplaceholder.typicode.com/posts");
    if (response.status === 200) {
      const data = await response.json(); // Await the JSON parsing
      return data;
    } else {
      throw new Error(`Error fetching data. Status: ${response.status}`);
    }
  } catch (error) {
    console.error("An error occurred:", error.message);
    // Handle the error gracefully (e.g., show a user-friendly message)
    return null;
  }
}

// Usage
try {
  const result = await getData();
  if (result && result.length > 0) {
    console.log("Data received:", result);
  } else {
    console.log("Failed to fetch data.");
  }
} catch (error) {
  console.error("An error occurred during data retrieval:", error.message);
}

ব্যাখ্যাঃ

  • getData ফাংশনটিকে একটি async function হিসেবে ডিফাইন করা হয়েছে। এর মানে এটি সর্বদা একটি প্রমিস প্রদান করে।
  • আমরা fetch('...') রিকোয়েস্ট সম্পন্ন হওয়ার জন্য অপেক্ষা করছি এনং এর রেসপন্স হ্যান্ডল করার জন্য সরাসরি getData() ফাংশনে await ব্যবহার করেছি।
  • রেসপন্স স্ট্যাটাস 200 হলে, আমরা JSON ডেটা পার্স করছি - response.json()
  • যদি কোনো এরর হয় (যেমন, non-200 স্ট্যাটাস বা নেটওয়ার্ক সমস্যা), আমরা একটি ত্রুটি নিক্ষেপ করি এবং সেটিকে try/catch ব্লক-এ ধরছি।
  • Usage সেকশনটিতে দেখানো হয়েছে, কিভাবে getData() ফাংশনকে কল করতে হয় এবং রেজাল্ট/এরর হ্যান্ডল করতে হয়।

4. 🗃️ জাভাস্ক্রিপ্টে Closures-গুলো আসলে কি?

ক্লিক করে বিস্তারিত দেখুন

ক্লোজার জাভাস্ক্রিপ্টের একটি মৌলিক ধারনা। এটি ঘটে যখন একটি ফাংশন এক্সিকিউশন (কার্যকারিতা) শেষ হওয়ার পরেও তার লেক্সিকাল স্কোপ মনে রাখে। সহজ কথায়, একটি ক্লোজার একটি ফাংশনকে তার বাইরের (ঘিরে রাখা) ফাংশনের ভেরিয়েবলগুলিতে অ্যাক্সেস বজায় রাখতে দেয় বা মনে রাখে, এমনকি যখন সেই বাইরের ফাংশনটির এক্সিকিউশন সম্পন্ন হয় তখনও।

🧩 সহজ-সরল উপমাঃ পিকনিক বাস্কেট

কল্পনা করুন আপনি বন্ধুদের সাথে পিকনিকে যাচ্ছেন। আপনি সমস্ত প্রয়োজনীয় জিনিস সহ একটি পিকনিকের ঝুড়ি প্যাক করুন: স্যান্ডউইচ, ফল, পানীয় এবং আনুষঙ্গিক জিনিসপত্র। আপনি পার্কে যাওয়ার সময়, আপনি আপনার সাথে ঝুড়িটি বহন করেন। এখন, এখানে আকর্ষণীয় অংশ: ঝুড়ি নিজেই একটি ক্লোজারের মত!

❇️ দ্যা বাস্কেট (Closure):

  • ✨ পিকনিকের ঝুড়ি আপনার পিকনিকের জন্য প্রয়োজনীয় সমস্ত কিছুকে ধারণ/এনক্যাপসুলেট করে।
  • ✨ এটি ভেতরের বস্তুগুলোকে আবদ্ধ করে দেয়, সেগুলিকে গোপন ও সুরক্ষিত রাখে৷
  • ✨ একইভাবে, জাভাস্ক্রিপ্টে একটি ক্লোজার একটি নির্দিষ্ট কন্ট্যাক্সের/প্রসঙ্গের মধ্যে থাকা ভেরিয়েবল এবং ফাংশনগুলিকে এনক্যাপসুলেট করে রাখে।

🔥 ক্লোজার কিভাবে কাজ করে?

  1. ℹ️ লেক্সিকাল স্কোপ:

    • ✨ জাভাস্ক্রিপ্ট লেক্সিকাল স্কোপিং ব্যবহার করে, যার অর্থ হল ফাংশনগুলোর তাদের ধারণকারী (প্যারেন্ট) ফাংশনে ডিফাইন করা ভেরিয়েবলগুলিতে অ্যাক্সেস রয়েছে৷
    • ✨ যখন একটি ফাংশন ডিফাইন করা হয়, তখন এটি তার আশেপাশের স্কোপকে ক্যাপচার করে বা মনে রাখে, একটি ক্লোজার তৈরি করে।
  2. ℹ️ একটি ক্লোজার তৈরি করা: একটি ক্লোজার তৈরি হয় যখন:

    • ✨ একটি অভ্যন্তরীণ ফাংশনকে একটি বাইরের ফাংশনের মধ্যে ডিফাইন করা হয়।
    • ✨ ভিতরের ফাংশন বাইরের ফাংশন থেকে ভেরিয়েবলকে রেফারেন্স করে।
    • ✨ অভ্যন্তরীণ ফাংশনটিকে রিটার্ন করা হয় অথবা অন্যান্য ফাংশনের আর্গুম্যান্ট হিসেবে পাস করা হয়।

🔥 ব্যবহারিক ক্ষেত্র এবং সুবিধাগুলি

  • ℹ️ ডেটার গোপনীয়তা:

    • ✨ একটি ক্লোজারের মধ্যে ভেরিয়েবলগুলিকে আবদ্ধ করে, আপনি গোপন ভেরিয়েবল তৈরি করেন।
    • ✨ এই ভেরিয়েবলগুলি শুধুমাত্র ক্লোজারের স্কোপের মধ্যেই অ্যাক্সেসযোগ্য, ডেটার গোপনীয়তা প্রদান করে৷
    • ✨ এই পদ্ধতিটি অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং-এর প্রাইভেট মেথডের অনুকরণ করে।
  • ℹ️ বিশেষ ফাংশন (ফাংশন কারখানা):

    • ✨ আপনি ক্লোজার ব্যবহার করে বিশেষ ফাংশন (ফাংশন কারখানা) তৈরি করতে পারেন। উদাহরণস্বরূপ, একটি ফাংশন বিবেচনা করুন যা একটি প্রারম্ভিক মানের উপর ভিত্তি করে এর সংশ্লিষ্ট আরো ফাংশন তৈরি করে।
  • ℹ️ ইভেন্ট হ্যান্ডলিং:

    • ✨ যখন আপনি একটি HTML এলিমেন্টের উপর একটি ইভেন্ট হ্যান্ডলার (যেমন একটি ক্লিক ইভেন্ট) সংযুক্ত করেন, আপনি একটি ক্লোজার তৈরি করছেন।
    • ✨ ইভেন্ট হ্যান্ডলার ফাংশন পার্শ্ববর্তী কনট্যাক্স (ভেরিয়েবল, ফাংশন) মনে রাখে - এমনকি এটি এলিমেন্ট থেকে বিচ্ছিন্ন হওয়ার পরেও৷
  • ℹ️ টাইমআউট এবং বিরতি:

    • ✨ টাইমআউট এবং বিরতি, setTimeout or setInterval পরিচালনার জন্য ক্লোজার অপরিহার্য।
    • ✨ তারা নিশ্চিত করে যে কলব্যাক এক্সিকিউট করার সময় সঠিক কনট্যাক্স বজায় রাখা হয়েছে।

🕹️ এখন যেহেতু আমরা মুল জিনিসটি বুঝতে পেরেছি, আসুন নিচের উদাহরণগুলো দেখা যাক।

উদাহরনঃ Data Privacy

function createCounter() {
  let count = 0;
  return function () {
    count += 1;
    return count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
// 'count' is not accessible from outside the 'createCounter' function.

ব্যাখ্যাঃ

  • createCounter ফাংশন একটি count ভেরিয়েবলকে এনক্যাপসুলেট করে। এটি একটি বেনামী ফাংশন রিটার্ন করে যেটিকে কল করা হলে, count-কে ১ করে বৃদ্ধি করে এবং সেি ভ্যালুটি রিটার্ন করে।
  • count ভেরিয়েবলটি গোপন থাকছে এবং সরাসরি createCounter এর বাইরে একে অ্যাক্সেস বা পরিবর্তন করা যাবে না।

উদাহরনঃ Function Factories

function makeMultiplier(multiplier) {
  return function (number) {
    return number * multiplier;
  };
}

const double = makeMultiplier(2);
console.log(double(5)); // 10

ব্যাখ্যাঃ

  • makeMultiplier ফাংশনটি একটি আর্গুমেন্ট নেয় multiplier এবং একটি নতুন ফাংশন রিটার্ন করে। এই রিটার্নকৃত ফাংশনটি একটি আর্গুমেন্ট নেয় number এবং numbermultiplier এর গুণফল রিটার্ন করে।
  • makeMultiplier দ্বারা তৈরি প্রতিটি ফাংশন তার নিজস্ব multiplier মান ধরে রাখে।

উদাহরনঃ Event Handling

let countClicks = (function () {
  let count = 0;
  return function () {
    count += 1;
    console.log(`Button clicked ${count} times`);
  };
})();

document.getElementById("myButton").addEventListener("click", countClicks);

ব্যাখ্যাঃ

  • countClicks-টি IIFE (তাৎক্ষণিকভাবে কল করা ফাংশন এক্সপ্রেশন) ক্লিক সংখ্যা গণনার জন্য একটি গোপন count ভেরিয়েবল তৈরি করে।
  • রিটার্নকৃত ফাংশনটি ক্লিকের জন্য একটি ইভেন্ট হ্যান্ডলার হিসাবে ব্যবহৃত হয়েছে, যা গণনা ১ করে বৃদ্ধি করে এবং ভ্যালুটিকে কনসলে লগ করে।

উদাহরনঃ Timeouts and Intervals

function delayedAlert(message, delay) {
  setTimeout(function () {
    alert(message);
  }, delay);
}

delayedAlert("Hello after 2 seconds", 2000);

ব্যাখ্যাঃ

  • delayedAlert ফাংশনটি একটি ক্লোজার প্রদর্শন করে যেখানে setTimeout-এর ভিতরে বেনামী ফাংশন message এবং delay প্যারামিটারগুলোকে ব্যবহার করছে।
  • এমনকি delayedAlert এক্সিকিউশন শেষ হওয়ার পরেও, কলব্যাক ফাংশন এখনও message এবং delay-কে অ্যাক্সেস করতে পারে।

5. 🔄 আসুন বুঝি জাভাস্ক্রিপ্টের ইভেন্ট লুপ ও অ্যাসিঙ্ক্রোনাস আচরন

Click to expand details

জাভাস্ক্রিপ্ট সিঙ্গেল-থ্রেডেড, যার মানে এটি একবারে একটি কাজই প্রোসেস করতে পারে। অন্যদিকে, এটি একটি ইভেন্ট লুপ ব্যবহার করে দক্ষতার সাথে অ্যাসিঙ্ক্রোনাস কাজগুলি পরিচালনা করতে পারে। চলুন বুঝি কিভাবে এটা কাজ করে:

1️⃣ মেইন থ্রেড

  • আপনি যখন জাভাস্ক্রিপ্ট কোড চালান, এটি মূল থ্রেডেই কার্যকর হয়।
  • যেকোনো সিঙ্ক্রোনাস কোড (যেমন ফাংশন কল, অ্যাসাইনমেন্ট বা লুপ) ক্রমানুসারে চলে।

2️⃣ অ্যাসিঙ্ক্রোনাস টাস্ক

  • অ্যাসিঙ্ক্রোনাস কাজগুলি (যেমন, একটি API থেকে ডেটা আনা, ফাইল পড়া, বা ব্যবহারকারীর ইনপুটের জন্য অপেক্ষা করা) মূল থ্রেডকে ব্লক করে না।
  • এই কাজগুলি ব্রাউজারের Web API-তে পাঠানো হয় (যেমন setTimeout, fetch, বা addEventListener)।
  • ফলাফলের জন্য অপেক্ষা করার সময়, প্রধান থ্রেড অন্যান্য কোড রান করতে থাকে।

3️⃣ কলব্যাক কিউ

  • যখন একটি অ্যাসিঙ্ক্রোনাস টাস্ক সম্পূর্ণ হয়, এটি কলব্যাক কিউতে তার কলব্যাক (মুল কাজ চালানোর জন্য একটি ফাংশন) ফাংশনটিকে রাখে।
  • কলব্যাক কিউ অপেক্ষমান ফাংশনটিকে ধারণ করে কার্যকর হওয়ার জন্য।

4️⃣ ইভেন্ট লুপ

ইভেন্ট লুপ ক্রমাগত চেক করে:

  • কল স্ট্যাক (যেখানে ফাংশন কার্যকর হয়) কি খালি কিনা?
  • কলব্যাক কিউতে কিছু আছে কিনা?
  • কল স্ট্যাক খালি থাকলে, ইভেন্ট লুপ কিউ থেকে পরবর্তী কলব্যাক বাছাই করে এবং এটি কার্যকর করার জন্য কল স্ট্যাকে পাঠিয়ে দেয়।

⏱️ Web APIs ও setTimeout এক্সিকিউশন

1️⃣ setTimeout এক্সিকিউশন

  • জাভাস্ক্রিপ্ট Web APIs গুলো অ্যাক্সেস করতে পারে (যেমন, setTimeout, fetch, addEventListener)। এগুলি অ্যাসিঙ্ক্রোনাস এবং অন্যান্য অপারেশনের সাথে সমান্তরালভাবে চলতে পারে।
  • যখন আপনি setTimeout(callback, delay) কল করেন, এটি নির্দিষ্ট বিলম্বের পরে কলব্যাক ফাংশন কার্যকর হওয়ার জন্য সময়সূচি নির্ধারণ করে।
  • ব্রাউজার একটি Web API-তে (জাভাস্ক্রিপ্ট ইঞ্জিনের বাইরে) এই কলব্যাক ফাংশনটিকে পাঠিয়ে দেয়।
  • নির্দিষ্ট বিলম্বের জন্য অপেক্ষা করার সময় মূল থ্রেডটি অন্য কোড চালনা করতে থাকে।
  • বিলম্বের পরে, কলব্যাক ফাংশনটিকে কলব্যাক কিউতে পাঠানো হয়।

2️⃣ ইভেন্ট লুপ

ইভেন্ট লুপ ক্রমাগত চেক করে:

  • কল স্ট্যাক (যেখানে ফাংশন কার্যকর হয়) কি খালি কিনা?
  • কলব্যাক কিউতে কিছু আছে কিনা?
  • কল স্ট্যাক খালি থাকলে, ইভেন্ট লুপ কিউ থেকে পরবর্তী কলব্যাক বাছাই করে এবং এটি কার্যকর করার জন্য কল স্ট্যাকে পাঠিয়ে দেয়।

🤝 মাইক্রোটাস্ক কিউ ও Promises এক্সিকিউশন

জাভাস্ক্রিপ্ট প্রমিসগুলো অ্যাসিঙ্ক্রোনাস অপারেশনগুলিকে আরও মার্জিতভাবে পরিচালনা করে মাইক্রোটাস্ক কিউ ব্যবহার করে:

1️⃣ Promise এক্সিকিউশন:

  • একটি প্রমিস এমন একটি মান উপস্থাপন করে যা এখনও পাওয়া যায়নি এমন হতে পারে (যেমন, একটি API থেকে ডেটা)।
  • যখন একটি প্রমিস সমাধান করে বা প্রত্যাখ্যান করে (resolves বা rejects), এটি তার কলব্যাক (.then() বা .catch()) চালানোর জন্য নির্ধারিত করে।
  • প্রমিসগুলি মাইক্রোটাস্ক কিউ ব্যবহার করে (এর অগ্রাধিকার কলব্যাক কিউর চেয়ে বেশী)।

2️⃣ ইভেন্ট লুপ ও মাইক্রোটাস্ক:

  • বর্তমান টাস্ক (যেমন, একটি সিঙ্ক্রোনাস ফাংশন) চালানোর পরে, ইভেন্ট লুপ মাইক্রোটাস্ক কিউ চেক করে।
  • যদি সমাধানের প্রমিস(প্রতিশ্রুতি) অপেক্ষারত থাকে তবে তাদের কলব্যাকগুলি কার্যকর করা হয়।
  • এটি নিশ্চিত করে যে কলব্যাক কিউ থেকে পরবর্তী টাস্কের আগে প্রমিসগুলিকে পরিচালনা করা হয়।

📝 সংক্ষেপে, setTimeout callback queue ব্যবহার করে, যেখানে প্রমিস microtask queue ব্যবহার করে। ইভেন্ট লুপ উভয়ই পরিচালনা করে এবং নিশ্চিত করে যেন অ্যাসিঙ্ক্রোনাস কাজগুল দক্ষভাবে পরিচালইত হয় 🔁। মনে রাখবেন, ইভেন্ট লুপ নিশ্চিত করে যে অ্যাসিঙ্ক্রোনাস কাজগুলি মেইন থ্রেডকে ব্লক না করে সময় সাপেক্ষ কজগুলো চলমান থাকার সময়ও যেন আপনার অ্যাপ্লিকেশনটি প্রতিক্রিয়াশীল (রেসপন্সিভ) থাকে! 💪

🕹️ এখন যেহেতু আমরা মুল জিনিসটি বুঝতে পেরেছি, আসুন নিচের উদাহরণগুলো দেখা যাক।


উদাহরনঃ setTimeout

console.log("Start");
setTimeout(() => {
  console.log("Timeout callback");
}, 1000);
console.log("End");

// Output:
/* 
'Start'
'End'
(After 1 second) 'Timeout callback' 
*/

ব্যাখ্যাঃ

  • Start এবং End সিঙ্ক্রোনাসভাবে চলেছে।
  • setTimeout এর কলব্যাকটি 1 সেকেন্ডের পরে চলার জন্য নির্ধারিত হয়েছে, তবে এটি মূল থ্রেডটিকে ব্লক করছে না।
  1. প্রাথমিক এক্সিকিউশন:

    • console.log('Start') স্টেটমেন্ট প্রথমে এক্সিকিউট হয়, Start লগ করে।
    • এর পরে, setTimeout ফাংশন কল হয়, যা কলব্যাক ফাংশনটিকে 1000 মিলিসেকেন্ড (1 সেকেন্ড) পরে চালানোর জন্য নির্ধারিত করে।
    • অবশেষে, console.log('End') স্টেটমেন্ট এক্সিকিউট করে, End লগ করে।
  2. ইভেন্ট লুপ এবং Web API:

    • setTimeout কলব্যাকটি অ্যাসিঙ্ক্রোনাস এবং Web API-এ পাঠানো হয়৷
    • প্রধান থ্রেড অন্য কোড বাধাহীনভাবে চালতে থাকে।
  3. সময়সীমার সমাপ্তি:

    • 1 সেকেন্ডের পরে, Web APIs সংকেত দেয় যে সময় শেষ হয়ে গেছে।
    • কলব্যাক ফাংশনটি (console.log('Timeout callback')) কলব্যাক কিউতে রাখা হয়েছে।
  4. কলব্যাক কিউ এবং ইভেন্ট লুপ:

    • কল স্ট্যাক খালি কিনা ইভেন্ট লুপ চেক করে।
    • যেহেতু স্ট্যাক খালি তাই কলব্যাকটি কিউ থেকে মেইন থ্রেডে/কল স্ট্যাকে পাঠানো হয়েছে৷
    • কলব্যাকটি এক্সিকিউট হয়, Timeout callback লগ করে।
  5. চূড়ান্ত আউটপুট অর্ডার:

    • Start
    • End
    • (1 সেকেন্ড পর) Timeout callback

উদাহরনঃ Promise

const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve("Data fetched"), 1000);
  });
};

fetchData().then((result) => {
  console.log(result);
});
console.log("Fetching data...");

// Output:
/* 
'Fetching data...'
(After 1 second) 'Data fetched'
*/

ব্যাখ্যাঃ

  • fetchData একটি প্রমিস প্রদান করে যা 1 সেকেন্ড পরে সমাধান হয়।
  • .then() কলব্যাক প্রমিস সমাধানের জন্য অপেক্ষা করে।
  • ইতিমধ্যে, মূল থ্রেড এক্সিকিউশন চালিয়ে যাচ্ছে Fetching data...
  1. প্রাথমিক এক্সিকিউশন:

    • fetchData ফাংশন একটি প্রমিস প্রদান করে।
    • console.log('Fetching data...') স্টেটমেন্ট এক্সিকিউট হয়, Fetching data... লগ করে।
  2. প্রমিস এক্সিকিউশন:

    • প্রমিস 1 সেকেন্ডের পরে সমাধান হয় (setTimeout এর কারণে)।
    • সমাধান করা মান (Data fetched) কলব্যাক কিউতে রাখা হয়েছে।
  3. কলব্যাক কিউ এবং ইভেন্ট লুপ:

    • কল স্ট্যাক খালি কিনা ইভেন্ট লুপ চেক করে।
    • এটি .then() কলব্যাকটিকে কল স্ট্যাকে নিয়ে যায়।
    • কলব্যাক এক্সিকিউট হয়, Data fetched লগ করে।
  4. চূড়ান্ত আউটপুট অর্ডার:

    • Fetching data...
    • (1 সেকেন্ড পরে) Data fetched