Kısım II · İnşaat · Bölüm 25
JavaScript: Bir dil olarak
Değerlerden bekleyen işlere (JavaScript as a language)
Neden burada: CSS sunumu kurdu; davranışı yazan dilin kuralları olmadan DOM kodu bir ezber listesine dönüşür. Burada tarayıcı belgesini kısa süre kenara koyuyoruz: puanı hesaplayan dil ile puanı ekrana yazdıran API aynı parça değil.
Neye dayanıyor: Bölüm 9: değişken, fonksiyon, koşul, döngü ve hata türleri; Bölüm 21: dinamik tip, motor, bellek yönetimi ve dil–çalıştırma ayrımı.
- Kat 10Bizim uygulamamızSorular, puan, günlük seri ve can kuralları.
- Kat 9Web ve tarayıcıHTML belgeyi, CSS sunumu, JavaScript davranışı kurar; bu bölümün çalışma alanı.
- Kat 7–8İşletim sistemi ve ağDosyaları, süreçleri ve veri alışverişini sağlar; belge bunların üstünde çalışır.
- Kat 0–6Bitten işlemciye, belleğe ve dillereÖnceki bölümlerde kurduğumuz temel. Tam kat planı.
Bölümün sonunda değerin tipini, adın kapsamını, nesne referansını ve sonra çalışacak devamı ayırabileceksin. Sonraki bölümde bunları karta bağlayacağız.
25.1 Değerler ve tipler: let ve const
Şimdi bir süre soru kartını ve tarayıcı belgesini kenara koyalım. 10 + 5 hesabının bir başlığa veya düğmeye ihtiyacı yoktur. JavaScript önce bir programlama dilidir: değerleri, adları, fonksiyonları ve çalışma kuralları vardır. DOM'a dokunmak bu dilin tarayıcı tarafından sağlanan API'leri kullanmasıdır; dilin kendisiyle aynı şey değildir. Bölüm 9'da C ile öğrendiğin değişken, koşul ve fonksiyon fikirlerini burada yeniden icat etmeyeceğiz; onların JavaScript'teki davranış sınırlarını kuracağız.19
Değer (value), programın üzerinde işlem yaptığı somut veridir. Tip (type), o değerin hangi işlemlere nasıl katılacağını anlamamızın parçasıdır. Bölüm 21.3'te JavaScript'in dinamik tipli olduğunu gördün: bir let değişkenini ömrü boyunca tek bir tipte tutmak zorunda değilsin. Bu, değerlerin tipi olmadığı anlamına gelmez. “Adın bağlı olduğu değer değişebilir” ile “değerin ne olduğunu bilmiyoruz” farklı cümlelerdir.12
| Tip veya değer | Örnek | Hukuk alıştırmasında neyi temsil edebilir? |
|---|---|---|
| Sayı (number) | 10, 0.5 | Puan, ilerleme oranı; bu tip hem tamsayı hem kesirli değerleri kapsar. |
| Karakter dizisi (string) | "Hukuka Giriş" | Soru başlığı; C'deki elle yönetilen sonlandırıcılı diziyle aynı kullanım modeli değildir. |
| Boole (boolean) | true, false | Cevap değerlendirildi mi, doğru mu? |
null | let secilen = null; | Örneğimizde “henüz şık seçilmedi” diye bilerek koyduğumuz boşluk işareti. |
undefined | let secilen; | Başlangıç değeri verilmemiş değişken; olmayan nesne özelliğini okuduğunda da çıkabilir. |
| Nesne (object) | { puan: 10, can: 3 } | Birbirine ait alanları toplama; birazdan soru ve durum nesnelerinde kullanacağız. |
Tablo tam tip listesi değildir: bigint ve symbol da vardır. Nesne olmayan temel değerler ilkel değerler (primitive values) olarak anılır. 4.4’teki kayan nokta sınırları sürer; burada küçük tamsayı puanları seçmemiz parasal hesaplar için genel çözüm değildir.1
let puan = 0;
puan = puan + 10;
const soruSayisi = 2;
const durum = { can: 3 };
durum.can = 2;
İlk satır değişkeni bildirir ve başlangıç değerini atar. İkinci satır eski değerden yeni değer hesaplayıp aynı ada bağlar; = hâlâ atamadır, eşitlik sorusu değildir. Üçüncü satırdaki const bağı yeniden atamaya kapatır: sonradan soruSayisi = 3 yazamazsın. Dördüncü satırda ise bir nesne oluşturup sabit bağa koyarız. Beşinci satır o bağın işaret ettiği nesnenin alanını değiştirir; const bunu engellemez. Sabit bağ ile değiştirilemez nesne aynı şey değildir.2
Sayı gibi görünen metin, sayı değildir
const metin = "10";
console.log(metin + 5);
console.log(Number(metin) + 5);
console.log(metin === 10);
İlk satır tırnaklı bir karakter dizisi oluşturur. İkinci satır konsola "105" değerini yazar: artı işlemi burada metin birleştirmeye gider. Üçüncü satır önce Number ile açık dönüşüm yapar ve 15 yazar. Son satırdaki ===, örtük tip dönüşümü yapmadan karşılaştırır; metin ile sayı aynı olmadığından false yazar. console.log, değerleri geliştirme konsoluna yazdırmak için kullandığımız ortam aracıdır; ekrandaki soru kartını güncellemez. İleride form girdisini puana dönüştürürken bu fark, görünmez bir hata kaynağı olabilir.13
null ve undefined için de kör dönüşüm yerine anlam seç: 0 puan, geçerli bir sonuçtur; null ise bizim modelimizde henüz seçilmemiş cevap olabilir. İkisini “boş” diye aynı davranışa zorlamak iş kuralını bozabilir. typeof null'ın "object" vermesi dildeki tarihsel bir tuzaktır; null kontrolü için deger === null kullanılır. Bu sonucu “null nesnedir” diye yorumlama.1
25.2 Fonksiyonlar, ok fonksiyonu, kapsam, kapanış
Bölüm 9.4'te fonksiyonu adlandırılmış küçük bir iş olarak kurmuştuk. JavaScript'te de parametreler tanımdaki girdi adları, argümanlar çağrıda verilen gerçek değerlerdir. return dönüş değerini verir ve o çağrının çalışmasını bitirir. Fonksiyon, yalnızca hesap yapan bir yazım kısaltması değil, bir sınırdır: “buraya ne veriyorum, buradan ne alıyorum?” sorusunun kod karşılığıdır.3
function puanHesapla(dogruMu, bonus) {
if (!dogruMu) return 0;
return 10 + bonus;
}
const sonuc = puanHesapla(true, 5);
console.log(sonuc);
İlk satır fonksiyonu ve iki parametresini tanımlar. İkinci satırda ! Boole değerini ters çevirir; cevap doğru değilse sıfır döndürülür, aşağıdaki satıra inilmez. Üçüncü satır doğru cevap için örnekte seçtiğimiz temel puanı bonusla toplar. Kapanış, fonksiyonun gövdesini bitirir; henüz çağrı değildir. Son iki satır, true ve 5 argümanlarıyla çağırır, çıkan 15 değerini adlandırır ve konsola yazar. Bu bir ürün kuralı önerisidir, JavaScript'in zorunlu puan sistemi değil.3
const ikiKat = (puan) => puan * 2;
console.log(ikiKat(10));
Ok fonksiyonu (arrow function) bir fonksiyon değeri yazmanın kısa biçimidir. İlk satırdaki (puan) parametre, => ayırıcı, puan * 2 ifade gövdesidir; bu kısa biçimde ifadenin sonucu döner. İkinci satır fonksiyonu çağırıp 20 yazar. Süslü parantezli gövdeye geçersen dönüş istiyorsan return yazman gerekir. Ok fonksiyonlarının this bağlama davranışı gibi başka farkları da vardır; “bütün function yazımlarını düşünmeden oka çevir” kuralı çıkarmıyoruz.3
Kapsam: bir adı nereden görebiliyorum?
Kapsam (scope), bir değişkene kodun hangi bölgesinden erişilebildiğini belirler. let ve const blok kapsamlıdır: if içindeki süslü parantezlerde tanımlanan ad dışarıdan görünmez. Fonksiyon parametreleri ve yerel adları da o çağrının çalışma alanındadır. JavaScript'te adın nerede arandığını belirleyen temel ilişki, fonksiyonun nerede yazıldığına bağlı sözcüksel yapıdır; yalnızca nereden çağrıldığına değil.24
const temel = 10;
function hesapla(bonus) {
const toplam = temel + bonus;
return toplam;
}
console.log(hesapla(5));
İlk satır dış kapsamda bir değer kurar. Fonksiyonun içindeki bonus parametresi ve toplam yereldir; fonksiyon ayrıca dıştaki temel'i okuyabilir. return yerel değişkenin kendisini dışarı taşımak zorunda olmadan sonucunu döndürür. Son satırın çıktısı 15'tir. Dışarıda console.log(toplam) denersen o ad bu kapsamda tanımlı olmadığı için hata alırsın. Birkaç sorunun aynı değişken adını kullanabilmesi, bu sınırların yararıdır.24
Kapanış: dış çağrı bitti, bağa erişim bitmedi
function sayacKur() {
let cevapSayisi = 0;
return () => {
cevapSayisi = cevapSayisi + 1;
return cevapSayisi;
};
}
const say = sayacKur();
console.log(say());
console.log(say());
İlk satır üreticiyi, ikinci satır her üretici çağrısına özgü bağı kurar. İçten dönen fonksiyon bu aynı bağı artırıp döndürür. Dış çağrı bitse de say bağı görebilir; son iki çağrı 1 ve 2 yazar. Fonksiyonun oluşturulduğu sözcüksel çevreye erişimini korumasına kapanış (closure) diyoruz.4
Bu, bütün yerel değişkenlerin diske kaydedildiği anlamına gelmez. Erişilebilen fonksiyon ve onun kullandığı çevre, çalışma sırasında yaşamaya devam eder; bellek yönetimi Bölüm 21.4'teki motorun sorumluluğundadır. İkinci kez sayacKur() çağırırsan bağımsız bir sayaç kurarsın. Bu örnek cevap sayısını sayar; günlük seriyi hesaplamaz. Kapanışı burada tanımamızın nedeni, sonraki bölümde olay dinleyicisinin daha önce kurulmuş duruma nasıl eriştiğini anlayabilmek.4
25.3 Nesne ve dizi; JSON'a ilk bakış
Bir soruyu ayrı ayrı metin, siklar, dogruIndeks adlarıyla taşımak küçük örnekte kolaydır. Soru sayısı artınca hangi metnin hangi cevapla eşleştiğini korumak zorlaşır. Nesne (object), ilişkili özellikleri anahtar–değer çiftleriyle bir arada tutabilir. Bölüm 21.5'te nesne fikrini sınıflarla tanımıştık; JavaScript'te sıradan bir nesne oluşturmak için önce bir sınıf tanımlamak zorunda değilsin.5
const soru = {
metin: "Bu örnekte kural etiketi hangi şıkla eşleşiyor?",
siklar: ["Genel ifade", "Tekil olay"],
dogruIndeks: 0
};
console.log(soru.siklar[0]);
İlk süslü parantez nesneyi açar. metin bir karakter dizisine, siklar bir diziye, dogruIndeks bir sayıya bağlanır; virgüller özellikleri ayırır. soru.siklar nokta yazımıyla özelliği okur; [0] onun ilk elemanını seçer. Çıktı Genel ifade olur. İçerik, yazılımı açıklamak için seçilmiş yapay soru verisidir; burada bir hukuk önermesinin doğruluğunu kanıtlamıyoruz.56
Dizi (array), sıralı değerleri indeksleriyle tutar. JavaScript dizisinin indeksi C'deki gibi sıfırdan başlar; fakat C'deki “aynı tipte, sabit boyutlu bitişik hücreler” açıklamasını JavaScript motorunun fiziksel yerleşimine aynen taşımayız. JavaScript dizileri nesnelerdir, büyüyebilir ve farklı tipte değerler taşıyabilir. Yine de bizim soru dizimizde benzer biçimdeki nesneleri birlikte tutmak okunabilirliği artıran bir tasarım kararıdır.6
const sorular = [soru];
sorular.push({ metin: "İkinci kart", siklar: ["A", "B"], dogruIndeks: 1 });
console.log(sorular.length);
for (const kart of sorular) {
console.log(kart.metin);
}
İlk satır önceki nesneyi bir diziye koyar. push yeni nesneyi sona ekler; const dizi içeriğinin değişmesini engellemez. length bu boşluksuz örnekte 2'dir. for…of her turda sıradaki değeri kart adıyla verir, içteki satır onun metnini yazar. Kapanış döngünün gövdesini bitirir. Seyrek dizilerde length gerçek dolu eleman sayısıyla aynı olmak zorunda değildir; bu örnek öyle bir dizi kurmuyor.6
Atama nesneyi çoğaltmaz
const asil = { puan: 0 };
const diger = asil;
diger.puan = 10;
console.log(asil.puan);
İlk satır bir nesne kurar; ikinci satır bağımsız kopya oluşturmaz, aynı nesneye ikinci bir referans verir. Üçüncü satır o ortak nesneyi değiştirir; son satır 10 yazar. Bölüm 10.6'daki değer ve referans ayrımı burada yeniden görünür. JavaScript fonksiyonlarına argüman da değer olarak aktarılır; nesne söz konusuysa kopyalanan değer aynı nesneye giden referanstır. Bu yüzden nesnenin alanını değiştirmek dışarıdan görünür olabilir, parametreye tamamen başka nesne atamak ise çağıranın bağını kendiliğinden değiştirmez.13
JSON nesne değil, veri metnidir
JSON (JavaScript Object Notation), yapılandırılmış veriyi metin olarak yazma biçimidir. Adında JavaScript geçer, fakat Go gibi başka diller de bu biçimi okuyup üretebilir. Nesne bellekte kullanılan bir değerdir; JSON ise dosyada, ağda veya tarayıcı saklamasında taşınabilecek bir metin temsilidir. Nesneye benzemesi ikisinin aynı şey olduğunu göstermez.7
const kayit = { puan: 10, can: 3 };
const metinKaydi = JSON.stringify(kayit);
const geri = JSON.parse(metinKaydi);
console.log(geri.can);
İlk satır sıradan bir nesne kurar. İkinci satır JSON.stringify ile {"puan":10,"can":3} metnini üretir. Üçüncü satır JSON.parse ile bu metinden yeni bir nesne değeri okur. Son satır 3 yazar. JSON'da özellik adları çift tırnaklıdır; fonksiyon gövdeleri, yorumlar ve undefined normal JSON değerleri değildir. “Her JavaScript nesnesini hiçbir kayıp olmadan JSON'a çeviririm” sonucu çıkmaz. Buradaki basit kayıt, JSON'un taşıyabildiği verilerden kurulmuştur; ayrıntıları Bölüm 35'te büyüteceğiz.7
25.4 Kontrol akışı ve hata yakalama
Kontrol akışı (control flow), bir sonraki adımda hangi kodun çalışacağını belirler. C'den bildiğin if/else, for ve while aynı temel sorulara cevap verir: hangi yolu seçiyorum, neyi tekrarlıyorum? Bir cevabı değerlendirmek için karşılaştırma gerekir; puanı güncellemek için atama gerekir. Bu ikisini birbirinin yerine okumamak, hâlâ ilk hata önleme alışkanlığımızdır.86
let puan = 0;
let can = 3;
const dogruMu = 1 === 0;
if (dogruMu) {
puan = puan + 10;
} else {
can = can - 1;
}
İlk iki satır örnek başlangıç durumudur. Üçüncü satır seçili indeks 1'i doğru indeks 0 ile karşılaştırdığı için false üretir. Koşul yanlış olduğundan doğru dalındaki puan satırı çalışmaz; else içindeki can azaltma çalışır. Sonuç puan 0, can 2'dir. Süslü parantezler dalların sınırını kurar. Bu hesapları Python ile de doğruladık; davranışın seçimi JavaScript'in if kurallarına, miktarlar ise bizim örnek kuralımıza dayanır.8
Koşulun içine her zaman açık bir Boole değeri gelmeyebilir. Boş olmayan "false" metni, içindeki sözcük “yanlış” dese de koşulda doğru gibi değerlendirilir. Bu nedenle sunucudan veya formdan gelen metni, sırf ekranda bir sözcük var diye doğrudan doğruluk kararı yerine koyma. Örneğimizde secilen === soru.dogruIndeks gibi anlamı açık bir karşılaştırmayı tercih ediyoruz.8
Beklenmeyen veri ile normal yanlış cevap aynı şey değildir
try {
const kayit = JSON.parse("bozuk veri");
console.log(kayit.puan);
} catch (hata) {
console.log("Kayıt okunamadı.");
}
try bloğu başarısız olabilecek işlemi sınırlar. İçindeki ilk satır geçerli JSON olmayan metni okumaya çalışır; bu bir hata fırlatır. Aynı bloktaki sonraki console.log çalışmaz. catch, fırlatılan hatayı hata adıyla alır ve örneğimizde okunabilir mesaj yazar. Programın ne yapacağına biz karar veririz: örneğin yeni bir alıştırmaya başlanabilir veya veri bozulduğu söylenebilir. Hatayı yakalamak onun nedenini otomatik düzeltmek değildir.78
throw new Error("…") ile kendi geçersiz durumunu da hata olarak bildirebilirsin; örneğin beklenen sayı alanının metin çıkması. Ancak kullanıcının yanlış şıkkı seçmesi, bizim ürünümüzde normal bir sonuçtur; her yanlış cevap için istisna fırlatmak zorunda değiliz. Bölüm 9.6'daki ayrım hâlâ geçerli: bozuk sözdizimi, çalışma zamanı hatası ve mantık hatası farklıdır. Geçerli ama yanlış hesap yapan kodu try/catch kendiliğinden fark etmez; ayrıca, bütün dosyanın ayrıştırılmasını engelleyen bir sözdizimi hatasını o dosyada daha sonra çalışacak catch ile kurtaramazsın.8
25.5 JavaScript motoru ve Node.js
JavaScript motoru (JavaScript engine), kaynak kodu ayrıştırıp çalıştıran parçadır. Bölüm 21.2'de gördüğün yorumlama ve anında derleme seçeneklerini burada yeniden ayrıntılandırmayacağız. Şimdi eklediğimiz ayrım şu: motor, içinde bulunduğu ortamın tamamı değildir. Tarayıcı motora belge, olay, ağ gibi imkânlar sunar; JavaScript dilindeki bir nesne veya fonksiyon, tek başına HTML belgesi yaratmaz.91
Node.js (JavaScript runtime environment), JavaScript'i tarayıcı dışında çalıştıran bir çalışma ortamıdır. V8 motorunu kullanır ve dosya, ağ gibi işler için kendi API'lerini sunar. Bu yüzden az önceki puan hesabı veya soru dizisi tarayıcı olmadan da yürütülebilir. Ama aynı ortamda tarayıcının document nesnesi kendiliğinden bulunmaz; “JS çalışıyor, o halde DOM da vardır” sonucu yanlıştır. Dilin taşınmasıyla ortam API'lerinin taşınmasını ayır.913
// hesap.js adlı dosyanın içeriği
console.log(puanHesapla(true, 5));
// Terminalde, fonksiyon da aynı dosyada tanımlıysa:
// node hesap.js
İlk satır dosya açıklamasıdır; çağrı, önceki fonksiyon da aynı dosyadaysa 15 yazar. Alttaki yorumlar terminal komutunu gösterir: node hesap.js. Kurulum ve araçlar Bölüm 29’da. Node.js’in varlığı, planlanan Go arka ucunu değiştirdiğimiz anlamına gelmez.9
25.6 Eşzamansız programlama: callback, Promise, async/await ve olay döngüsü
Bir puan toplamını hesaplamakla ağdan soru beklemek aynı türden iş değildir. İkinci işte işlemci çoğu zaman hesap yapmıyor, başka bir kaynaktan haber bekliyor. Eşzamansız programlama (asynchronous programming), uzun sürebilecek işi başlatıp bütün programı o sonucu bekleyen bir noktada kilitlemeden devam edebilme düzenidir. Bu, her JavaScript fonksiyonunun kendiliğinden başka bir işlemci çekirdeğine taşınması değildir.10
Geri çağırma (callback), başka bir koda argüman olarak verilen ve uygun zamanda o kod tarafından çağrılan fonksiyondur. Her geri çağırma eşzamansız olmak zorunda değildir; bir dizi üzerinde dolaşan yardımcı fonksiyon da verdiğin fonksiyonu aynı çağrı sırasında çalıştırabilir. Zamanlayıcıya verdiğimiz fonksiyon ise sonra çalıştırılmak üzere kaydedilir. setTimeout dilin salt aritmetiği değil, ortamın sağladığı zamanlayıcı API'sidir.31012
console.log("A: başlangıç");
setTimeout(() => console.log("B: zamanlayıcı"), 0);
Promise.resolve().then(() => console.log("C: söz devamı"));
console.log("D: eşzamanlı son");
İlk satır A'yı hemen yazar. İkinci satır fonksiyonu çalıştırmaz, zamanlayıcıya verir; sıfır gecikme “şu satırın ortasında hemen çağır” demek değildir. Üçüncü satır sonuçlanmış bir Promise için devam fonksiyonu kaydeder. Dördüncü satır D'yi yazar. Mevcut eşzamanlı çalışma bitince Promise devamı, sonra bu örnekteki zamanlayıcı geri çağırması yürür: sıra A → D → C → B. Bu sırayı Node.js'te çalıştırarak kontrol ettik; tarayıcının görev ve mikro görev açıklaması da aynı örüntüyü açıklar. Burada başka hazır olayların olmadığı bu küçük örneği konuşuyoruz; gerçek ağ yanıtlarının sırasını buradan çıkarmıyoruz.1112
Promise (Promise), daha sonra başarıyla sonuçlanabilecek veya reddedilebilecek bir işlemin sonucunu temsil eden nesnedir. Beklemede pending, başarıyla sonuçlanmış fulfilled, reddedilmiş rejected durumlarıyla düşünülür. Bir Promise işlemin sonucu değildir; o sonuca bağlanabildiğin temsilidir. .then başarı devamını, .catch hata devamını bağlamak için kullanılır. Zincirdeki her devamın ne döndürdüğü sonraki adımı etkiler.11
async function sonucOku() {
try {
const sonuc = await Promise.resolve(15);
console.log(sonuc);
} catch (hata) {
console.log("Sonuç alınamadı.");
}
}
sonucOku();
İlk satır async fonksiyon kurar; böyle bir çağrı Promise döndürür. try içinde await, burada 15 ile sonuçlanan Promise'in değerini alana kadar bu fonksiyonun devamını erteler. Diğer işler sırf bu bekleyiş yüzünden durmak zorunda değildir. Sonraki satır 15 yazar; beklenen Promise reddedilseydi hata catch tarafına giderdi. Kapanışlardan sonra fonksiyonu çağırıyoruz. Bu, ağdan veri çekilmiş gibi yapılmış bir çıktı değil; bilerek Promise.resolve ile oluşturduğumuz yerel bir dil örneğidir. Gerçek fetch isteği bir sonraki bölümde gelecek.11
Olay döngüsü, işletim sisteminin zamanlayıcısı değildir
Olay döngüsü (event loop), hazır işleri uygun sırada çalıştırma düzenidir. Basitleştirilmiş tarayıcı modelinde mevcut JavaScript işi biter, mikro görevler işlenir, sonra başka görevler ve çizim fırsatları gelir. Promise devamları mikro görevlerdendir; zamanlayıcının geri çağırması ayrı bir görev olabilir. “Bütün olaylar tek basit kuyruktadır” diye tüm ayrıntıları silmiyoruz; bu bölüm için önemli sınır, bekleyen devamın şu an çalışan kodu ortasından kesip yürümemesidir.12
Bölüm 14'te işletim sisteminin süreç ve iş parçacıklarına işlemci zamanı dağıttığını öğrendin. Olay döngüsü bunun yerine geçmez; bir çalışma ortamının içindeki iş düzenidir. Tarayıcıda uzun süren eşzamanlı bir döngü ana iş parçacığını meşgul ederse kullanıcı girdisini işlemek ve ekranı güncellemek aksayabilir. Fonksiyonun önüne yalnızca async yazmak o döngüyü başka çekirdeğe taşımaz. “Bekleyişi engellememek” ile “ağır hesabı paralel yapmak” ayrı problemlerdir.1012
Soru verisini nesne ve dizide, puan–can gibi geçici değerleri bir durum nesnesinde tutabilirsin. Doğru cevabı değerlendiren fonksiyon önce yalnızca değer alıp değer üretsin; ekrana yazmak ayrı iştir. Sunucudan yeni soru beklerken de “yükleniyor” durumunu tutacağız. Günlük seri, cevap sayacı değildir: bu bölümdeki kapanış sayacı gibi her çağrıda artırılmaz. Gün ve saat kuralı, kalıcı kayıt ve güvenilir sunucu kararını sonraki bölümlere bırakıyoruz. Bugün vanilla JS'te kurduğumuz dil zemini, hedef TypeScript ön yüzünü okumayı da kolaylaştıracak.
C bölümü fonksiyon ve kontrol akışını, bellek bölümü referansın kopyadan farkını, süreçler bölümü eşzamanlılığın zeminini kurmuştu. Dil haritası ise dinamik tip ve motor fikrini yerleştirdi. Artık “puan neden metin gibi birleşti”, “iki ad neden aynı nesneyi değiştirdi” ve “await neden bütün sayfayı dondurmadı” sorularını ayrı katlarda cevaplayabiliriz. Sıradaki bölüm, bu dilin tarayıcı belgesine uzandığı yer.
Bu bölümde neler kuruldu
JavaScript değerlerle çalışır; let yeniden atamaya, const sabit bağa izin verir. Fonksiyonlar değer olabilir; kapsam erişimi, kapanış oluşturulduğu çevreyle ilişkiyi belirler. Nesneler alanları, diziler sıralı değerleri toplar; JSON bunların uygun verilerini metin olarak taşır. Kontrol akışı ve hata yolları ayrıdır. Motoru barındıran ortam hangi API’lerin bulunduğunu belirler; Promise ve async/await bekleyen işlerin devamını düzenler, hesabı kendiliğinden paralelleştirmez.
Terimler sözlükte, Bölüm 25 başlığı altında. İkinci anlatım için CS50’nin yazılı Hafta 8 notlarındaki ilgili HTML/CSS/JavaScript bölümleri de bu iş bölümünü örnekler.14
MDN · Functions: Defining functions, Calling functions, Function scopes and closures. Derinleşme: javascript.info · Variable scope, closure — Lexical Environment; MDN · How to use promises — async and await.
Takıldığın yeri yapay zekâ öğretmenine sor. Öğretmeninden bir const nesnesi, bir kapanış ve bir zamanlayıcı içeren kısa örnek yazmasını iste. Çıktıyı önce sen tahmin et; sonra tek tek hangi bağın ve hangi devamın çalıştığını birlikte denetleyin.
Bölüm sonu soruları
Önce kitaba bakmadan cevapla; sonra gerekçeyi ve ilgili alt bölümü oku.
Örnek cevabı göster
Geri çağırma, başka koda verdiğim fonksiyondur; ne zaman çağrılacağı o kodun sözleşmesine bağlıdır. Bir dizi yardımcısı aynı çağrı içinde çalıştırabilir; setTimeout daha sonraki görev için kaydeder. Fonksiyon olmak ile sonra çalışmak aynı özellik değildir. Bkz. 25.6.
Örnek cevabı göster
Önce mevcut eşzamanlı işte A ve D yazılır; sonra Promise devamı olan mikro görev C, ardından örnekteki zamanlayıcı görevi B gelir. Sıfır gecikme mevcut kodun ortasında kesme değildir. await ilgili async fonksiyonun devamını erteler; bütün programı paralel yürütmez veya ağır döngüyü başka çekirdeğe taşımaz. Bkz. 25.6.
Kaynaklar
- MDN · JavaScript data types and data structures.
- MDN · Grammar and types.
- MDN · Functions.
- javascript.info · Variable scope, closure.
- javascript.info · Objects.
- javascript.info · Arrays.
- MDN · Working with JSON.
- MDN · Control flow and error handling.
- Node.js · Introduction to Node.js.
- MDN · Introducing asynchronous JavaScript.
- MDN · How to use promises.
- javascript.info · Event loop: microtasks and macrotasks.
- Node.js · Differences between Node.js and the Browser.
- CS50 · Lecture 8 notes, JavaScript başlığı.