Scope, Hoisting & Execution Context

"The Engine Room of JavaScript"

স্বাগতম জাভাস্ক্রিপ্টের "ইঞ্জিন রুমে"। এতদিন আমরা কোড লিখেছি, কিন্তু কখনো ভাবিনি কোডটা ব্রাউজারে রান করার সময় ঠিক কী ঘটে? কেন ভেরিয়েবল ডিক্লেয়ার করার আগেই অ্যাক্সেস করা যায় (Hoisting)? কেন let এরর দেয় কিন্তু var দেয় না?

এই অধ্যায়টি তোমাকে Junior Coder থেকে Senior Engineer এ রূপান্তর করবে। কারণ ইন্টারভিউতে ৮০% কঠিন প্রশ্ন এখান থেকেই আসে।

১. Execution Context: যেখানে কোড বেঁচে থাকে

জাভাস্ক্রিপ্ট কোড হাওয়ায় ভেসে বেড়ায় না। কোড রান করার জন্য তার একটি পরিবেশ বা এনভাইরনমেন্ট লাগে। একেই বলে Execution Context (EC)

সাধারণত ৩ ধরণের EC থাকে:

  • Global Execution Context (GEC): ফাইল রান করার সাথে সাথেই এটা তৈরি হয়। (ব্রাউজারে এটা window, Node.js এ global)
  • Function Execution Context (FEC): যখনই কোনো ফাংশন কল (Call) করা হয়, তার জন্য একটি নতুন বক্স বা এনভাইরনমেন্ট তৈরি হয়
  • Eval: (এটি আমরা ব্যবহার করব না, কারণ এটি সিকিউর নয়)

⚙️ কোড রান হওয়ার ২য় ধাপ (The Two Phases)

সিনিয়র হিসেবে এটা জানা ফরজ। কোড রান করার সময় JS Engine দুই ধাপে কাজ করে:

Phase 1: Creation Phase (Memory Allocation) 🧠

  • কোড রান হয় না, শুধু স্ক্যান করা হয়
  • var ভেরিয়েবলগুলোর জন্য মেমোরি বুক করা হয় এবং মান রাখা হয় undefined
  • function ডিক্লারেশনগুলো সম্পূর্ণ মেমোরিতে লোড হয়ে যায়
  • this এর মান সেট করা হয়

Phase 2: Execution Phase (Code Execution) 🏃‍♂️

  • লাইন বাই লাইন কোড রান হয়
  • ভেরিয়েবলের আসল মান বসানো হয় (Variable Assignment)
  • ফাংশন এক্সিকিউট হয়

২. Call Stack: কাজের সিরিয়াল খাতা

জাভাস্ক্রিপ্ট Single Threaded ল্যাঙ্গুয়েজ। অর্থাৎ সে একবারে একটার বেশি কাজ করতে পারে না। এই কাজের হিসাব রাখার জন্য সে "Call Stack" ব্যবহার করে।

function one() {
  console.log("One");
  two();
}

function two() { 
  console.log("Two");
}

one();

Stack Flow:

  • GEC (Global Context) স্ট্যাকে প্রথমে ঢোকে
  • one() কল হলো → one() স্ট্যাকের ওপরে বসল
  • one() এর ভেতর two() কল হলো → two() স্ট্যাকের সবার ওপরে বসল
  • two() এর কাজ শেষ → সে স্ট্যাক থেকে বের হয়ে গেল (Pop)
  • one() এর কাজ শেষ → সেও বের হয়ে গেল
  • সবশেষে GEC বের হলো

Senior Insight:

যদি তুমি এমন লুপ লেখো যা থামে না (Infinite Recursion), তাহলে এই স্ট্যাক ভরে উপচে পড়ে। একেই বলে "Stack Overflow"

⭐ ৩. Hoisting: ভুতুড়ে আচরণ!

Hoisting মানে "উপরে তোলা"। কিন্তু আসলে কোড উপরে উঠে না। মেমোরি ক্রিয়েশন ফেজে ভেরিয়েবল মেমোরিতে জায়গা পায় বলে মনে হয় যেন তারা উপরে উঠে গেছে।

A) var Hoisting (The Weird One)

console.log(age); // Output: undefined (Error না!)
var age = 25;
console.log(age); // Output: 25

কেন? কারণ Creation Phase-এ age মেমোরিতে জায়গা পেয়েছে এবং ডিফল্ট ভ্যালু undefined সেট হয়েছে।

B) Function Hoisting (The Good One)

greet(); // ✅ কাজ করবে!

function greet() {
  console.log("Hello Senior Dev!");
}

কেন? কারণ function declaration সম্পূর্ণ মেমোরিতে লোড হয়।

C) let & const Hoisting (TDZ Trap)

এরাও Hoisted হয়, কিন্তু মেমোরিতে ইনিশিয়ালাইজ হয় না।

console.log(score); // ❌ ReferenceError: Cannot access 'score' before initialization
let score = 100;

এই যে scope শুরু থেকে let ডিক্লেয়ার করার লাইন পর্যন্ত সময়টা—একে বলে TDZ (Temporal Dead Zone)। এখানে ভেরিয়েবল থাকলেও ধরা যায় না।

৪. Scope: কার অ্যাক্সেস কোথায়?

স্কোপ মানে হলো "এলাকা"। কার ক্ষমতা কতটুকু।

Global Scope:

সবার জন্য উন্মুক্ত। (বিপজ্জনক, কারণ যে কেউ ডাটা চেঞ্জ করতে পারে)

Function Scope (var's playground):

ফাংশনের ভেতরে যা আছে, তা বাইরে যাবে না।

Block Scope (let/const):

{ ... } এই ব্র্যাকেটের ভেতরের জিনিস বাইরে যাবে না।

⚠️ Why var is bad? (Scope Leaking)

var ব্লক স্কোপ মানে না। সে দেয়াল ভেদ করে বেরিয়ে আসে।

if (true) {
  var leak = "I am Leaking!";
}
console.log(leak); // Output: "I am Leaking!" (ভয়ংকর ব্যাপার!)

যদি let ব্যবহার করতে, তাহলে এরর দিত এবং কোড সেইফ থাকত।

⭐ ৫. Lexical Scope (Scope Chain)

এটা একটু ট্রিকি, কিন্তু খুব লজিক্যাল। Lexical Scope মানে হলো: একটি ফাংশন কোথায় কল হয়েছে সেটা ম্যাটার করে না, কোথায় লেখা (Defined) হয়েছে সেটা ম্যাটার করে

শিশুর যেমন তার বাবা-মায়ের সম্পত্তিতে অধিকার থাকে, তেমনি ইনার ফাংশন (Inner Function) তার আউটার ফাংশনের (Outer Function) ভেরিয়েবল অ্যাক্সেস করতে পারে।

let dad = "Money";

function family() {
    let son = "Toy";
    
    function play() {
        // son তার নিজের স্কোপে 'Toy' পাবে
        // বাবার স্কোপ থেকে 'Money' পাবে
        console.log(son, dad); 
    }
    play();
}
family();

JS ইঞ্জিন প্রথমে নিজের স্কোপে খোঁজে, না পেলে প্যারেন্ট স্কোপে যায়, সেখানে না পেলে গ্লোবালে যায়। একে বলে Scope Chain

৬. this Keyword (Brief Intro)

this হলো একটি কনটেক্সট পয়েন্টার

  • গ্লোবাল স্কোপে this = window
  • অবজেক্টের মেথডে this = সেই অবজেক্ট
  • Arrow Function: এর নিজস্ব this নেই। সে তার প্যারেন্টের this ধার করে (Lexical this)

(আমরা OOP অধ্যায়ে this নিয়ে বিস্তারিত পোস্টমর্টেম করব)

🧠 ৭. Senior Level Interview Questions

Q1: Output কী হবে এবং কেন?

var a = 1;
function b() {
    a = 10;
    return;
    function a() {} // 😲 Trick here!
}
b();
console.log(a);

Answer: 1। কারণ: ফাংশন b এর ভেতরে function a() {} হোয়িস্টিং হয়ে উপরে উঠে যায় এবং লোকাল a ভেরিয়েবল হিসেবে কাজ করে। তাই a=10 গ্লোবাল a কে পরিবর্তন করে না, বরং লোকাল a কে পরিবর্তন করে।

Q2: IIFE কী?

IIFE (Immediately Invoked Function Expression) হলো যে ফাংশন তৈরির সাথে সাথেই রান হয়। আগে এটি স্কোপ আইসোলেশনের জন্য ব্যবহার হতো।

(function() {
    console.log("I run immediately!");
})();

🚀 অধ্যায় ৪ সারাংশ (Checklist)

আমরা যা শিখলাম:

  • Execution Context: কোড রান হওয়ার পরিবেশ
  • Creation Phase: যেখানে ভেরিয়েবল মেমোরি পায় (Hoisting ঘটে)
  • Execution Phase: যেখানে আসল কোড রান হয়
  • Scope Chain: নিজের কাছে না পেলে ওপরে খোঁজ করা (Lexical Environment)
  • TDZ: let/const ডিক্লেয়ার করার আগের নিষিদ্ধ এলাকা
  • Avoid var: কারণ এটি স্কোপ লিক করে

Next Step: এই মেমোরি এবং স্কোপের জ্ঞান নিয়ে আমরা এখন ডেটা স্ট্রাকচারের গভীরে যাব। পরের অধ্যায়: "Arrays — Core to Advanced Operations"।

🔒 কপিরাইট সুরক্ষিত কন্টেন্ট 🔒

কপি, স্ক্রিনশট, প্রিন্ট করা সম্পূর্ণ নিষিদ্ধ।