Gelişmiş JavaScript: Olay döngüsü

Dec 01 2022
İşleyişini sıfırdan keşfederek JavaScript'te ustalaşalım Hiç tanımlanmamış hatalarla karşılaştınız mı veya bir değişkenin kapsamını belirlemekte zorlandınız mı? Kodun nasıl çalıştığını bilmeden herhangi bir hatayı ayıklamak gerçekten çok zaman alıyor. Bu blogda, yürütme bağlamı, çağrı yığını ve geri arama sırası açısından olay döngüsü gibi gelişmiş kavramların gerçekte nasıl çalıştığını göstereceğim.

İşleyişini sıfırdan keşfederek JavaScript'te ustalaşalım

Fotoğraf: Unsplash'ta Marc St

Hiç tanımlanmamış hatalarla karşılaştınız mı veya bir değişkenin kapsamını belirlemekte zorlandınız mı?

Kodun nasıl çalıştığını bilmeden herhangi bir hatayı ayıklamak gerçekten çok zaman alıyor.

Bu blogda, ile ilgili olarak ve gibi gelişmiş kavramların gerçekte event loopnasıl çalıştığını göstereceğim.execution contextcall stackcallback queue

Bir sorumluluk reddi beyanı — Kavramlar inanılmaz derecede bilgi yoğundur ve birbiriyle bağlantılıdır, bu nedenle lütfen gözlerinizi bile kırpmayın!

JavaScript Motoru

Google'ın V8 motoru, bir JavaScript Motorunun iyi bilinen bir örneğidir. Örneğin, hem Chrome hem de Node.js, V8 motorunu kullanır. Temel olarak, V8 motoru iki bölümden oluşur -

  1. Call Stack : Tüm kodlar onun içinde yürütülür. Yığın veri yapısı gibi çalışır, yani LIFO(Son Giren İlk Çıkar) konseptini takip eder.
  2. Bellek Yığını: Bellek tahsisinin gerçekleştiği yer. Yığın Veri Yapısının aksine, bu sadece bir anı.

Genel Yürütme Bağlamı veya GEC, bir betik dosyası alındığında JavaScript motoru tarafından oluşturulan varsayılan Yürütme Bağlamı'dır.

Bir işlevin içinde olmayan tüm JavaScript kodları GEC. Aşağıdaki adımlar GEC

  • Tüm değişkenleri ve işlevleri küresel ölçekte depolamak için bir Bellek Alanı oluşturun
  • Küresel bir nesne oluşturun.
  • Anahtar kelimeyi oluşturthis

Kodunuzun çalıştırılacağı yere bağlı olarak nerede bulunacağını belirleyecektir this. Örneğin, Node.js'de ayrı bir global nesneye işaret ederken, tarayıcıda windownesneye işaret eder.

Tarayıcı Konsolu

Çağrı Yığını (veya İşlev Yürütme Yığını)

JavaScript single-threadedzaten duymuş olduğunuz gibi . Ama gerçekte ne anlama geliyor?

Bu, bir JavaScript motorunun yalnızca bir call stackveya function execution stack.

  • Bildiğimiz gibi, derleyici kodunuzu ilk kez araştırdığında, JS motorundan derleyici tarafından bir Global Execution Contextveya oluşturması GECve ayrıca onu Call Stack.
  • Tüm kodunuz içinde birer birer yürütülür Global Execution Contextve işlev tanımı veya değişken bildirimi için bellek ayırır ve orada saklar.
  • Ancak herhangi bir işlev çağrısı bulunduğunda, işlevin kodunu yürütmek için bir Functional Execution Contextveya FEColuşturulur ve ardından call stack.
  • call stackYorumlayıcı , işlevin her sona erişinde bir işlevi kaldırır . Bir işlev, kapsamının sonuna veya bir dönüş ifadesine ulaştığında sona erer.
  • Son olarak, kodunuzun tamamını yürütmek GEC, Call Stack.

Merak etmeyin, bir örnekle gösterelim.

function f1{
  console.log('f1');
}

f1();
console.log('end');

Adım 2: — Örneğimizde, olan 1. satır yürütülecektir f1. Tanımı için bir hafıza tahsis edilecek f1ve saklanacaktır.

Adım 3: — 2. satırda bir fonksiyon çağrılır. Bu işlev çağrısı için bir Function Execution Context veya FEColuşturulacak ve Call Stack.

Adım 4: — Şimdi, tüm f1()satır satır yürütülecek ve yürütmeyi bitirdikten sonra Call Stack.

Adım 5: — Ardından, son satır console.log('end')çalıştırılacak ve konsolda 'end' yazdırılacaktır. Son olarak, tüm kodunuzu yürütmek Global Execution Context, Call Stack.

JS, eşzamansız görevleri nasıl yönetir?

Hepimizin bildiği gibi JavaScript, eşzamanlı , tek iş parçacıklı bir dildir (her seferinde bir görev) ve tek iş parçacığı, call stackiçine giren her şeyi hemen yürütür.

Peki ya 5 saniye sonra bir şey uygulamamız gerekirse? Bunu içeride yapabilir miyiz call stack?

Hayır, yapamayız. Çünkü call stackzamanlayıcı yok. Ama bunu nasıl yapabiliriz?

JavaScript çalışma zamanının devreye girdiği yer burasıdır .

JavaScript Çalışma Zamanı Ortamı

DOM olaylarının tümü, Global Yürütme Bağlamında (GEC) tüm özelliklerini kullanmak için JavaScript Motoruna erişim sağlayan Web API'lerinin parçaları setTimeout()olsa console.log()da , JavaScript'in bir parçası olmadığını şimdi söylersem içim parçalanabilir. küresel nesne Bu web API'lerine eşzamansız denir .window

Geri Arama Sırası nedir?

"Geri arama kuyruğu" veya "görev kuyruğu" olarak adlandırılan bir görevler sırası, çağrı yığınının mevcut görevleri tamamlandıktan sonra yürütülen bir sıradır. Web API'sinde kaydedilen görevler, web API'sinden geri arama kuyruğuna taşınır.

Geri arama kuyruğu, bir kuyruk veri yapısı gibi çalışır; bu, görevlerin sıraya eklendikleri sırayla işlendiği anlamına gelen bir çağrı yığınının aksine, görevlerin FIFO düzeninde (ilk giren ilk çıkar) işlendiği anlamına gelir.

Geri Arama Sırası

Olay Döngüsü nedir?

Bir JavaScript olay döngüsü, çağrı yığını boşalır boşalmaz geri arama kuyruğundan çağrı yığınına FIFO sırasına göre bir görev ekler.

Çağrı yığını şu anda bazı kodlar çalıştırıyorsa ve yığın bir kez daha boşalana kadar sıradan başka çağrılar eklemiyorsa, olay döngüsü engellenir. Bunun nedeni, JavaScript kodunun tamamlanacak şekilde çalıştırılmasıdır.

Yukarıdaki kavramları bir örnekle anlayalım.

  • İlk başta Global Execution Contextbizim için kodumuzu oluşturur call stackve GECkodumuzu satır satır çalıştırır.
  • GEC1. satırı yürütür ve konsolumuza 'Başlat' yazdırır.
  • 2. satır yürütülürken setTimeout()web API çağrılır ve ardından setTimeout()zamanlayıcı özelliğine erişim sağlar. 5000msArdından gecikme süresi olarak ayarlayabileceksiniz .
  • callBack()İşlevi aracılığıyla geçirirken, setTimeout()web callBack()Web API üzerinden Geri Arama olarak kaydedilecektir.
  • Ardından GEC1. satırı yürütür ve konsolda 'End' yazar.
  • Tüm kod yürütüldüğünde, GECbizim call stack.
  • Ardından 5000 millisecond, callBack()içinde kayıtlı olan işlev web API, içinde taşınır call Back Queue.
  • Event loopişlevi callBack(), call Stackbittiğinde hepsi çalışır. Ve son olarak, callBack()işlev yürütülür ve konsola 'Geri Ara' yazdırılır.

function f1() {
    console.log('f1');
}

function f2() {
    console.log('f2');
}

function main() {
    console.log('main');
    
    setTimeout(f1, 0);
    
    f2();
}

main();

“f1”in “f2”den önce yazılacağını düşünüyorsanız, yanılıyorsunuz. Olacak -

main
f2
f1

Tartışılan JavaScript mekanizması, herhangi bir geri arama işlevi veya API isteği için uygundur.

2. örneğin runtime ortamında nasıl çalıştığını adım adım inceleyelim.

  1. Önce GECiçinde oluşturulacak call stackve daha sonra kod satır satır yürütülecektir GEC. Tüm işlev tanımlarını Bellek Yığınında saklar .
  2. çağrıldığında main(), a Function Execution Context (FEC)oluşturulur ve ardından çağrı yığınının içine girer. Bundan sonra, main()fonksiyonun tüm kodu satır satır yürütülecektir.
  3. Ana kelimeyi yazdırmak için bir konsol günlüğüne sahiptir. Böylece console.log('main')yürütülür ve yığından çıkar.
  4. Tarayıcı setTimeout()API'si gerçekleşir. Geri arama işlevi, onu geri arama sırasına koyar. Ancak yığında yürütme her zamanki gibi gerçekleşir, bu nedenle f2()yığına girer. Yürütmelerin konsol günlüğü f2(). İkisi de yığından çıkar.
  5. Ve sonra main()yığından da çıkar.
  6. Olay döngüsü, çağrı yığınının boş olduğunu ve kuyrukta bir geri arama işlevi olduğunu fark eder. Böylece, geri arama işlevi f1(), event loop. Yürütme başlar. Konsol günlüğü yürütülür ve f1()ayrıca yığından çıkar. Ve son olarak, daha fazla yürütmek için yığında ve kuyrukta başka hiçbir şey yok.

Bu benim pratiğim ve notum. Yararlı bulduysanız, lütfen aşağıdaki alkış simgesine tıklayarak desteğinizi gösterin. Medium'dan beni takip edebilirsiniz .