Bütün məqalələrə qayıt
Texnoloji Baxış

Pərdəarxası JavaScript: V8 Mühərriki, İcra Konteksti (Execution Context) və Yaddaşın Anatomiyası

Təməl sintaksisdən kənara çıxaraq JavaScript-in daxili arxitekturasını araşdırırıq: Kodun parse olunmasından Call Stack və Memory Heap idarəçiliyinə qədər bütün icra zənciri.

E

Elgun Mammadli

Front End Developer

Oct 7, 2026
6 dəq oxuma
Pərdəarxası JavaScript: V8 Mühərriki, İcra Konteksti (Execution Context) və Yaddaşın Anatomiyası

Əksər proqramçılar JavaScript ilə tanışlığa console.log("Hello World"), dəyişən təyinatları və ya funksiyalarla başlayır. Lakin dili dərindən anlamaq və Senior səviyyəsində sistem mühəndisliyi düşüncəsinə yiyələnmək üçün sintaksisin arxasında baş verən mühəndislik proseslərinə enmək vacibdir: Yazdığımız kod maşın üçün nə ifadə edir və JavaScript mühərriki onu kompüterin aparat təminatında (hardware) necə icra edir?

Bu məqalədə JavaScript-in daxili arxitekturasını, V8 mühərrikinin optimallaşdırma mexanizmlərini, İcra Kontekstinin (Execution Context) həyat dövrünü və yaddaş idarəetməsini araşdırırıq.


1. Mühərrikin Daxili Dünyası: Koddan Maşın Dilinə

JavaScript interpretasiya olunan deyil, müasir dövrdə JIT (Just-In-Time) Compilation ilə çalışan dildir. Dünyada ən məşhur JS mühərriki Google-un V8 mühərrikidir (Chrome, Node.js və Deno-da istifadə olunur).

Kodu brauzerə və ya Node.js mühitinə verdikdə proses aşağıdakı mərhələlərdən keçir:

pipeline-architecture.txt
Source Code 
    │
    ▼
[ Parser / Scanner ]  ──►  Token stream & AST (Abstract Syntax Tree)
    │
    ▼
[ Ignition ] (Interpreter) ──►  Bytecode  ──► İcra olunur
    │
    ├─► Profiler (Type Feedback & "Hot Code" analizi)
    │
    ▼
[ TurboFan ] (Optimizing Compiler) ──► Yüksək optimallaşdırılmış Maşın Kodu

Parser və AST (Mücərrəd Sintaksis Ağacı)

Mühərrik ilk növbədə leksik analiz aparır: kodu simvol-simvol oxuyaraq tokenlərə bölür. Daha sonra bu tokenlər əsasında sintaktik struktur — AST qurulur. AST kodun qrammatik iyerarxiyasını təmsil edən ağacvari məlumat strukturudur.

Ignition (İnterpreter)

V8-in Ignition adlı komponenti AST-ni oxuyur və onu platformadan asılı olmayan kompakt Bytecode-a çevirir. Bytecode maşın dilindən daha mücərrəddir, lakin dərhal icra edilə bilir. Bu, tətbiqin sürətlə start götürməsini təmin edir.

TurboFan və Profiler (JIT Optimallaşdırması)

Kod icra olunduqca mühərrikin daxilindəki Profiler sistemi hansı funksiyaların tez-tez çağırıldığını izləyir. Bu hissələr "Hot Code" adlanır. Profiler eyni zamanda arqumentlərin tiplərini (Type Feedback) qeydə alır.

Əgər funksiya davamlı olaraq eyni tipli arqumentlər qəbul edirsə, V8-in optimallaşdırıcı kompilyatoru olan TurboFan işə düşür və həmin Bytecode-u birbaşa CPU-nun anlayacağı maşın koduna (Machine Code) çevirir.

Deoptimallaşma (Deoptimization) Tələsi

JavaScript dinamik tiplidir. Əgər TurboFan bir funksiyanı rəqəmlər (number) üçün optimallaşdırıbsa və sonradan həmin funksiyaya mətn (string) ötürülərsə:

deoptimization.js
function add(a, b) {
  return a + b;
}

// TurboFan bu funksiyanı 'number' üçün optimallaşdırır (Inline Caching)
for (let i = 0; i < 10000; i++) {
  add(5, 10);
}

// Gözlənilməz tip dəyişikliyi:
add("5", "10"); // Deoptimization baş verir!

Mühərrik optimallaşdırılmış kodu ləğv edir (bailout) və yenidən yavaş Bytecode icrasına qayıdır. Monomorfik (sabit strukturlu) kod yazmağın performans baxımından əsas səbəbi məhz budur.


2. İcra Konteksti (Execution Context) Nədir?

Kod icra olunmağa başlayan andan etibarən JavaScript hər şeyi xüsusi mühitlərin — Execution Context (EC) daxilində idarə edir. Sadə dillə desək, Execution Context hazırda işləyən kodun "çalışma qutusu"dur.

İki əsas növü var:

  1. Global Execution Context (GEC): Kod işə düşdüyü an avtomatik yaranır. Tək bir qlobal kontekst mövcuddur. Brauzerdə window, Node.js-də global obyektini təyin edir.
  2. Function Execution Context (FEC): Hər dəfə bir funksiya çağırıldıqda həmin funksiya üçün ayrıca icra konteksti yaradılır.

Hər bir kontekst iki əsas fazadan keçir:

Faza 1: Creation Phase (Yaradılma Fazası)

Bu fazada kod hələ sətirbəsətir işlədilmir. Mühərrik kodu skan edir və yaddaş sahəsi ayırır:

  • Qlobal obyekt (window və ya global) təyin edilir.
  • this dəyişəni kontekstə bağlanır.
  • Lexical Environment və Variable Environment qurulur.
  • Dəyişənlər və funksiyalar üçün yaddaş ayrılır (Hoisting məhz burada baş verir).

Faza 2: Execution Phase (İcra Fazası)

Kod yuxarıdan aşağıya doğru sətirbəsətir icra olunur, dəyişənlərə real dəyərlər mənimsədilir və funksiyalar işə düşür.


3. Hoisting və Temporal Dead Zone (TDZ)-un Texniki Səbəbi

Dəyişənlərin yuxarı "qaldırılması" (hoisting) fiziki kod yerdəyişməsi deyil; bu, Creation Phase zamanı baş verən yaddaş qeydiyyatıdır.

Fərq mühərrikin dəyişən bəyannamələrini necə qeydiyyata almasındadır:

hoisting-tdz.js
console.log(a); // undefined
console.log(b); // ReferenceError: Cannot access 'b' before initialization

var a = 10;
let b = 20;
  • var açar sözü: Yaradılma fazasında yaddaşa yazılır və ona dərhal ilkin dəyər olaraq undefined mənimsədilir. İcra fazasında təyinata çatmamış müraciət etdikdə undefined qaytarır.
  • let və const açar sözləri: Yaradılma fazasında yenə yaddaşda qeydiyyata alınır, lakin onlara heç bir ilkin dəyər təyin edilmir. Dəyişənin yaradıldığı an ilə kodda ona faktiki dəyər mənimsədildiyi sətir arasındakı zonaya Temporal Dead Zone (TDZ) deyilir. Bu aralıqda dəyişənə müraciət ReferenceError xətası törədir.

4. Call Stack və Yaddaş Memarlığı: Stack vs Heap

JavaScript tək axınlı (single-threaded) dildir — yəni eyni anda yalnız bir əməliyyatı icra edə bilər. İcranın növbəliliyini Call Stack, məlumatların saxlanmasını isə Memory Heap idarə edir.

Xüsusiyyət Call Stack (Yığın) Memory Heap (Topa)
Məqsəd İcra axını, primitiv tiplər və ünvan göstəriciləri (pointers) Mürəkkəb obyektlər, massivlər, funksiyalar
Quruluş LIFO (Last In, First Out) strukturunda nizamlı yaddaş Qeyri-müntəzəm, dinamik böyüyə bilən geniş yaddaş sahəsi
Sürət Həddindən artıq sürətli çıxış Göstərici ilə müraciət edildiyi üçün nisbətən yavaş
memory-allocation.js
const id = 101;                                 // Stack-də saxlanılır
const user = { name: "Elgun", role: "Dev" }; // Obyekt Heap-də, referans ünvanı Stack-də

Stack-də yalnız Heap-dəki obyektin yaddaş ünvanı (0x0012FA) saxlanılır. İki dəyişəni bir-birinə bərabər etdikdə obyektin nüsxəsi deyil, Stack-dəki həmin ünvan köçürülür:

reference-mutation.js
const userA = { name: "Ali" };
const userB = userA; 

userB.name = "Murad";
console.log(userA.name); // "Murad" (Çünki hər ikisi Heap-də eyni ünvana baxır)

Call Stack və Stack Overflow

Hər bir funksiya çağırışı Call Stack-ə yeni bir çərçivə (Stack Frame) əlavə edir. Funksiya bitdikdə həmin çərçivə stack-dən atılır (pop). Sonsuz rekursiya baş verdikdə stack-in limiti aşılır və Maximum call stack size exceeded xətası yaranır.


5. Garbage Collection: Mark-and-Sweep

Heap-də dinamik yerləşən məlumatlar daim orada qala bilməz. Mühərrikin Garbage Collector (GC) komponenti artıq istifadə olunmayan yaddaşı təmizləyir.

Müasir mühərriklər Mark-and-Sweep (İşarələ və Süpür) alqoritmindən istifadə edir:

  1. Kök elementlər (Roots): Qlobal dəyişənlər, hazırda aktiv Call Stack-dəki lokal dəyişənlər kök sayılır.
  2. Mark (İşarələmə): GC köklərdən başlayaraq onların istinad etdiyi bütün obyektləri "əlçatan" (reachable) kimi işarələyir. Sonra həmin obyektlərin istinad etdiyi alt obyektləri də zəncirvari şəkildə tapır.
  3. Sweep (Süpürmə): Heç bir kökdən əlçatan olmayan (işarələnməmiş) obyektlərin yaddaşı azad edilir.

Yaddaş Sızması (Memory Leak) Təhlükəsi

Əgər obyektə artıq ehtiyac yoxdursa, lakin təsadüfən qlobal bir massivdə, silinməmiş hadisə dinləyicisində (addEventListener) və ya qapalı qalan closure-da referansı qalıbsa, GC onu silə bilmir. Nəticədə tətbiqin yaddaş sərfi getdikcə artır.


Xülasə

  • V8 Mühərriki kodu birbaşa şərh etmir; AST → Bytecode (Ignition) → Optimallaşdırılmış Maşın Kodu (TurboFan) pillələri ilə icra edir.
  • Execution Context kodun iş mühitidir; Creation və Execution fazalarından ibarətdir. Hoisting və TDZ birbaşa Creation fazasının arxitekturasıdır.
  • Stack və Heap fərqi məlumatın strukturunu müəyyən edir: Primitivlər və ünvanlar Stack-də, dinamik mürəkkəb strukturlar Heap-də saxlanılır.
  • Garbage Collector "əlçatanlıq" prinsipi ilə işləyir; istinadsız qalan obyektlər yaddaşdan təmizlənir.

Mühərrikin daxili mexanizmlərini mənimsədikdən sonra növbəti addım bu mühitin təbii davamı olan Scope Chain, Lexical Environment və Closures dərinliklərinə baxmaqdır.

Məqaləni paylaş

Pərdəarxası JavaScript: V8 Mühərriki, İcra Konteksti (Execution Context) və Yaddaşın Anatomiyası

Pərdəarxası JavaScript: V8 Mühərriki, İcra Konteksti (Execution Context) və Yaddaşın Anatomiyası | eTechmill