Bu doküman, ileri düzey bir JavaScript eğitim
programının detaylı müfredatını içeriyor. İstediğiniz kurallar doğrultusunda,
zaman sürelerini eklemeden, "Öğrenecekleriniz" bölümünü ve her konuyu
alt başlıklarıyla birlikte hiçbir özet yapmadan, detaylı açıklamalar, teorik
altyapılar, kod örnekleri ve pratik uygulamalarla ele alıyoruz.
Aşağıda müfredatın ilk büyük bölümü yer
almaktadır. İçeriğin derinliği ve detay seviyesi çok yüksek olduğu için anlatım
parça parça ilerleyecektir. Yarıda kaldığımda sizi bilgilendireceğim.
"Öğrenecekleriniz"
Paragrafının Açıklaması
Bu bölüm, kursun öğrencilere kazandırmayı
hedeflediği ana yetenekleri ve ileri düzey vizyonu özetler.
1. BÖLÜM:
Object Oriented JavaScript (Nesne Yönelimli
JavaScript)
Nesne Yönelimli Programlama (OOP), gerçek
dünyadaki varlıkları yazılım dünyasında nesneler (objects)
olarak modelleme biçimidir. JavaScript, prototip tabanlı bir OOP dilidir ancak
modern söz diziminde sınıf (class) yapılarını da tam
olarak destekler.
Working With Plain Old JavaScript Objects (Düz
Eski JavaScript Nesneleriyle Çalışmak)
JavaScript'te en temel nesne oluşturma yöntemi
süslü parantezler {} kullanarak yapılan nesne sabitleridir (Object Literals).
Bu nesneler key-value (anahtar-değer) çiftlerinden
oluşur.
Kod Örneği:
// Düz bir nesne tanımlama
const araba = {
marka: "Opel",
model: "Astra",
yil: 2022
};
// Özelliklere erişim ve değiştirme
araba.renk = "Kırmızı"; // Dinamik
ekleme
console.log(araba.marka); // "Opel"
Mixing Data & Functions With Objects (Veri ve Fonksiyonları Nesnelerle Karıştırmak)
Bir nesnenin içerisine sadece veri (özellikler)
değil, o veriyi işleyecek fonksiyonlar da (metotlar) eklenebilir.
Kod Örneği:
const kullanici = {
isim: "Ahmet",
soyisim: "Yılmaz",
tamIsimGoster: function() {
return `${this.isim} ${this.soyisim}`;
}
};
console.log(kullanici.tamIsimGoster()); // "Ahmet Yılmaz"
Class Basics
(Sınıf Temelleri)
Sınıflar, benzer özelliklere ve metotlara sahip
olacak nesneleri üretmek için kullanılan şablonlardır (mavi reçetelerdir).
Kod Örneği:
class Canli {
nefesAl() {
console.log("Nefes alınıyor...");
}
}
const insan = new Canli();
insan.nefesAl(); // "Nefes
alınıyor..."
Constructors (Yapıcı Fonksiyonlar)
Bir sınıftan new anahtar
kelimesiyle yeni bir nesne (örnek/instance)
oluşturulduğu an otomatik olarak çalışan özel metottur.
Kod Örneği:
class Kitap {
constructor(ad, yazar) {
this.ad = ad;
this.yazar = yazar;
}
}
const kitap1 = new Kitap("Nutuk", "Mustafa
Kemal Atatürk");
console.log(kitap1.ad);
// "Nutuk"
Practice Time: Bank Account
(Uygulama Zamanı: Banka Hesabı)
Sınıf, yapıcı fonksiyon ve temel nesne yapısını
birleştiren bir banka hesabı simülasyonu yapalım.
Uygulama Kodu:
class BankaHesabi {
constructor(sahip, bakiye = 0) {
this.sahip = sahip;
this.bakiye = bakiye;
}
paraYatir(miktar) {
this.bakiye += miktar;
console.log(`${miktar} TL yatırıldı. Güncel bakiye: ${this.bakiye} TL`);
}
paraCek(miktar) {
if (miktar > this.bakiye) {
console.log("Yetersiz bakiye!");
} else {
this.bakiye -= miktar;
console.log(`${miktar} TL çekildi. Kalan bakiye: ${this.bakiye} TL`);
}
}
}
const ahmetinHesabi = new BankaHesabi("Ahmet
Yılmaz", 500);
ahmetinHesabi.paraYatir(200); // 200 TL yatırıldı. Güncel bakiye: 700 TL
ahmetinHesabi.paraCek(1000); // Yetersiz bakiye!
ahmetinHesabi.paraCek(300); // 300 TL çekildi. Kalan bakiye: 400 TL
Instance Methods
(Örnek Metotları)
Bir sınıftan üretilen her bir nesnenin (instance) doğrudan erişebileceği ve üzerinde işlem
yapabileceği fonksiyonlardır.
Inheritance Basics (Kalıtım Temelleri)
Bir sınıfın, başka bir sınıfın özelliklerini ve
metotlarını devralarak kendi bünyesine katmasıdır. extends anahtar
kelimesiyle sağlanır.
Kod Örneği:
class Hayvan {
constructor(isim) {
this.isim = isim;
}
sesCikar() {
console.log("Bir ses çıkarıyor...");
}
}
class Kopek extends Hayvan {
havla() {
console.log("Hav! Hav!");
}
}
const kopek = new Kopek("Karabaş");
kopek.sesCikar(); // "Bir
ses çıkarıyor..." (Üst sınıftan geldi)
kopek.havla(); // "Hav! Hav!" (Kendi metodu)
The Super Keyword (super Anahtar Kelimesi)
Alt sınıfta, üst sınıfın constructor'ını
veya metotlarını çağırmak için kullanılan anahtar kelimedir.
Kod Örneği:
class Calisan {
constructor(isim, maas) {
this.isim = isim;
this.maas = maas;
}
}
class Yonetici extends Calisan {
constructor(isim, maas, departman) {
super(isim, maas); // Üst sınıfın constructor'ını tetikler
this.departman = departman;
}
}
const mudur = new Yonetici("Zeynep", 45000, "BT");
console.log(mudur.isim, mudur.departman); // "Zeynep BT"
Static Properties (Statik
Özellikler)
Nesneye değil, doğrudan sınıfın kendisine ait
olan değişkenlerdir.
Kod Örneği:
class Ayarlar {
static UYGULAMA_ADI = "BenimUygulamam";
}
const config = new Ayarlar();
console.log(config.UYGULAMA_ADI); // undefined (Nesneden erişilemez)
console.log(Ayarlar.UYGULAMA_ADI); // "BenimUygulamam" (Sınıftan erişilir)
Static Methods (Statik
Metotlar)
Doğrudan sınıf üzerinden çağrılan, nesne
oluşturulmasını gerektirmeyen metotlardır.
Kod Örneği:
class Matematik {
static topla(a, b) {
return a + b;
}
}
console.log(Matematik.topla(10, 20)); // 30
Use Cases For Static Methods
(Statik Metotlar İçin Kullanım Senaryoları)
Uygulama Kodu (Fabrika Metodu):
class Kullanici {
constructor(isim, rol) {
this.isim = isim;
this.rol = rol;
}
// Statik
Fabrika Metodu
static anonimYarat() {
return new Kullanici("Misafir
Kullanıcı", "Ziyaretçi");
}
}
const misafir = Kullanici.anonimYarat();
console.log(misafir.isim); // "Misafir Kullanıcı"
Ebook & ArrayUtils Exercises (E-Kitap ve Dizi Araçları Egzersizleri)
Sınıfları, statik metotları ve kalıtımı
pekiştirmek için iki ayrı egzersiz kodu kuralım.
Uygulama Kodu 1 (ArrayUtils
Egzersizi):
class DiziAraclari {
// Verilen
dizinin ortalamasını alan statik metot
static ortalamaBul(dizi) {
const toplam = dizi.reduce((acc, curr) => acc + curr, 0);
return toplam / dizi.length;
}
}
console.log(DiziAraclari.ortalamaBul([10, 20, 30, 40])); // 25
Uygulama Kodu 2 (Ebook
Kalıtım Egzersizi):
class Urun {
constructor(baslik, fiyat) {
this.baslik = baslik;
this.fiyat = fiyat;
}
}
class EKitap extends Urun {
constructor(baslik, fiyat, dosyaBoyutu) {
super(baslik, fiyat);
this.dosyaBoyutu = dosyaBoyutu;
}
}
const pdfKitap = new EKitap("JS
Rehberi", 150, "5MB");
console.log(pdfKitap.baslik, pdfKitap.dosyaBoyutu); // "JS Rehberi 5MB"
2. BÖLÜM: OOP:
Newer Features in
JavaScript (OOP: JavaScript'teki Yeni Özellikler)
Modern JavaScript standartlarıyla (ES2022 ve
civarı) birlikte nesne yönelimli yapılara güvenlik ve veri kapsülleme adına
kritik yenilikler gelmiştir.
Getters (Alıcılar)
Bir nesnenin özelliğini okumaya çalışırken arka
planda bir fonksiyon çalıştırıp geriye dinamik bir değer dönme işlemidir. get kelimesiyle tanımlanır.
Kod Örneği:
class Dikdortgen {
constructor(en, boy) {
this.en = en;
this.boy = boy;
}
// Getter
get alan() {
return this.en * this.boy;
}
}
const kare = new Dikdortgen(5, 5);
console.log(kare.alan); // 25 (Fonksiyon gibi parantez açıp kapatmadık!)
Setters (Ayarlayıcılar)
Bir nesne özelliğine yeni bir değer atanmaya
çalışıldığında devreye giren ve atanan değeri kontrol/filtre mekanizmasından
geçiren yapılardır. set kelimesiyle tanımlanır.
Kod Örneği:
class Sicaklik {
constructor(santigrat) {
this._santigrat = santigrat; // İç değişken
}
set fahrenheit(deger) {
this._santigrat = (deger - 32) * 5 / 9;
}
get santigrat() {
return this._santigrat;
}
}
const hava = new Sicaklik(0);
hava.fahrenheit = 32; // Set
tetiklendi
console.log(hava.santigrat); // 0
Practice Time: Getters
and Setters (Uygulama
Zamanı)
Bir kullanıcı profilindeki yaş ve e-posta
kontrolünü kapsayan güvenli yapı tasarlayalım.
Uygulama Kodu:
class Profil {
constructor(isim, yas) {
this.isim = isim;
this.yas = yas; // setter tetiklenecek
}
get yas() {
return this._yas;
}
set yas(yeniYas) {
if (yeniYas < 0) {
console.log("Hata: Yaş değeri negatif olamaz!");
this._yas = 0;
} else {
this._yas = yeniYas;
}
}
}
const user = new Profil("Can", -5); // "Hata: Yaş değeri negatif olamaz!"
console.log(user.yas); // 0
Public Fields (Açık Alanlar)
Constructor dışında,
sınıf gövdesinde doğrudan tanımlanan ve dışarıdan tamamen erişilebilen sınıf
özellikleridir.
Kod Örneği:
class SkorBord {
skor = 0; // Public Field
durum = "Başlamadı";
puanKazan() {
this.skor++;
}
}
const mac = new SkorBord();
mac.puanKazan();
console.log(mac.skor); // 1
Private Fields (Gizli Alanlar)
Sınıf dışından erişilmesi tamamen engellenmiş,
sadece sınıfın kendi içindeki metotlar tarafından okunup değiştirilebilen
özelliklerdir. # sembolü ile tanımlanır.
Kod Örneği:
class Kasa {
#sifre; // Private Field ilanı
constructor(ilkSifre) {
this.#sifre = ilkSifre;
}
sifreDegistir(eskiSifre, yeniSifre) {
if (this.#sifre === eskiSifre) {
this.#sifre = yeniSifre;
console.log("Şifre güncellendi.");
} else {
console.log("Eski şifre yanlış!");
}
}
}
const kasa = new Kasa("1234");
// console.log(kasa.#sifre); // HATA! SyntaxError
verir dışarıdan okunamaz.
kasa.sifreDegistir("1234", "5678"); // "Şifre
güncellendi."
Private Methods (Gizli
Metotlar)
Sadece sınıfın kendi içindeki diğer metotlar
tarafından çağrılabilen, dış dünyaya kapatılmış fonksiyonlardır. Yine # ile başlarlar.
Kod Örneği:
class BankaSistemi {
#logTut(mesaj) { // Gizli Metot
console.log(`[LOG - ${new Date().toLocaleTimeString()}]: ${mesaj}`);
}
islemYap() {
// İçeriden
güvenle çağrılır
this.#logTut("Kullanıcı işlem gerçekleştirdi.");
}
}
const sistem = new BankaSistemi();
sistem.islemYap();
// sistem.#logTut("Sızma testi"); // HATA! Sınıf dışından
ulaşılamaz.
ES2022 Static Initialization Blocks (Statik İlklendirme
Blokları)
Statik özellikleri (static
properties) başlatırken birden fazla satırdan oluşan,
mantıksal veya hata yönetimli (try-catch) karmaşık
işlemleri gerçekleştirmeyi sağlayan kod bloklarıdır.
Kod Örneği:
class VeriTabani Baglantisi {
static baglantiDurumu;
// Statik
Başlatma Bloğu
static {
try {
// Karmaşık
kurulum adımları simüle ediliyor
let baglandi mi = true;
if (baglandi mi) {
this.baglantiDurumu = "Aktif";
} else {
this.baglantiDurumu = "Pasif";
}
} catch (e) {
this.baglantiDurumu = "Hata";
}
}
}
console.log(VeriTabani Baglantisi.baglantiDurumu);
// "Aktif"
3. BÖLÜM: The Mysterious Keyword "This" (Gizemli
"This" Anahtar Kelimesi)
JavaScript'te this, fonksiyonun
nasıl yazıldığına değil, nasıl çağrıldığına bağlı olarak dinamik şekilde
değişen, mevcut yürütme bağlamını (execution context) işaret eden özel bir kelimedir.
Introducing This
& The Mystery of The Keyword This
(This ile Tanışma ve Gizemi)
Bir fonksiyon çalıştırıldığında, o anki işlem
alanını temsil eden bir nesneye ihtiyaç duyar. İşte this, o nesneyi
tutar. Dinamik yapısı nedeniyle JavaScript dünyasında en çok kafa karıştıran
konulardan biridir.
Global Objects
and This (Küresel Nesneler
ve This)
Eğer bir fonksiyon hiçbir nesneye bağlı olmadan,
düz bir şekilde global alanda çağrılırsa this global
nesneye yönlenir.
Kod Örneği:
function kontrolEt() {
console.log(this);
}
kontrolEt(); // Tarayıcıda 'window'
nesnesini basar.
function katiModKontrol() {
"use strict";
console.log(this);
}
katiModKontrol(); // 'undefined'
basar.
The "Left Of The Dot" Rule
(Noktanın Solundaki Kural)
Bir fonksiyon (metot) bir nesne üzerinden
çağrılıyorsa, fonksiyonun içindeki this anahtar
kelimesi nokta işaretinin solunda yer alan nesneyi gösterir.
Kod Örneği:
const dukkan = {
isim: "Merkez Şube",
selamla: function() {
console.log(`Hoş geldiniz, burası ${this.isim}`);
}
};
dukkan.selamla(); // Noktanın
solunda 'dukkan' var. This
= dukkan.
// Çıktı: "Hoş geldiniz,
burası Merkez Şube"
This and Classes (Sınıflar ve This)
Sınıfların içindeki metotlarda kullanılan this, o sınıftan new kelimesiyle
üretilen yeni nesne örneğinin (instance) kendisini
hedefler.
Kod Örneği:
class Oyuncu {
constructor(ad) {
this.ad = ad; // This, yeni üretilecek nesnedir.
}
}
const p1 = new Oyuncu("Hakan");
The Call Method (call Metodu)
Bir fonksiyonu, içerisindeki this bağlamını el ile (manuel) değiştirerek ve
parametreleri tek tek virgülle göndererek hemen çalıştırmaya yarayan yerleşik
metottur.
Kod Örneği:
function puanDurumu(MacSayisi, GolSayisi) {
console.log(`${this.isim} -> Maç:
${MacSayisi}, Gol: ${GolSayisi}`);
}
const forvet = { isim: "Icardi" };
// puanDurumu
içindeki 'this' artık 'forvet' nesnesi olacak
puanDurumu.call(forvet,
10, 8); // "Icardi -> Maç: 10, Gol: 8"
The Apply Method (apply Metodu)
call metodu ile
tamamen aynı işi yapar; tek farkı fonksiyona gönderilecek parametrelerin tek
tek değil, bir dizi (array) halinde
iletilmesidir.
Kod Örneği:
const defans = { isim: "Nelsson" };
// Parametreleri dizi olarak
yolluyoruz
puanDurumu.apply(defans,
[12, 1]); // "Nelsson -> Maç: 12, Gol: 1"
The Bind Method (bind Metodu)
Fonksiyonu hemen çalıştırmaz. İçerisindeki this kelimesini kalıcı olarak belirlediğimiz bir
nesneye bağlayarak bize yeni bir fonksiyon kopyası verir.
Kod Örneği:
const kaleci = { isim: "Muslera" };
// Kaleci nesnesine kilitlenmiş
yeni bir fonksiyon üretiyoruz
const kaleciPuani = puanDurumu.bind(kaleci);
// İlerleyen zamanlarda istediğimiz
an çağırabiliriz
kaleciPuani(15, 0); // "Muslera -> Maç: 15, Gol: 0"
Binding Arguments (Argümanları
Bağlamak)
bind metodu sadece
this bağlamını kilitlemekle kalmaz, fonksiyonun
alacağı ilk parametreleri de önceden sabitleyebilir. Buna fonksiyonel
programlamada kısmi uygulama (partial application) da denir.
Kod Örneği:
function vergiHesapla(oran, miktar) {
return miktar *
oran;
}
// Oran parametresini %18 (0.18) olarak kalıcı kilitliyoruz
const kdvHesapla = vergiHesapla.bind(null, 0.18);
// Artık sadece miktar girmemiz
yeterli
console.log(kdvHesapla(100)); // 18
console.log(kdvHesapla(500)); // 90
Bind With Event Listeners (Olay
Dinleyicilerle Bind Kullanımı)
HTML elementlerine olay dinleyici (event listener) eklendiğinde, callback fonksiyonunun içindeki this varsayılan
olarak olayı tetikleyen HTML elementine dönüşür. Sınıf metotlarımızın
bozulmaması için bind ile sabitleme yaparız.
Uygulama Kodu:
class Sayac Butonu {
constructor() {
this.tiklama Sayisi = 0;
this.button = document.createElement("button");
this.button.textContent = "Tıkla";
// bind(this) yapmazsak, tikla metodu içindeki this buton
elementini gösterir ve hata alırız.
this.button.addEventListener("click", this.tikla.bind(this));
document.body.appendChild(this.button);
}
tikla() {
this.tiklama Sayisi++;
this.button.textContent = `Tıklama: ${this.tiklama Sayisi}`;
}
}
Bind With Timers (Zamanlayıcılarla Bind
Kullanımı)
setTimeout veya setInterval gibi asenkron zamanlayıcılar çalıştırıldığında,
içlerindeki fonksiyonlar global bağlamda tetiklenir ve this kaybedilir. Bunu önlemek için fonksiyonu
bağlamamız gerekir.
Uygulama Kodu:
class Saat {
constructor() {
this.saniye = 0;
}
baslat() {
setInterval(function() {
this.saniye++;
console.log(this.saniye);
}.bind(this), 1000); // bind(this) ile sınıfın nesnesini
içeri aktardık.
}
}
Arrow Functions and This (Ok Fonksiyonları ve This)
Ok fonksiyonlarının (() => {}) kendilerine
ait bir this bağlamı yoktur.
Kod Örneği:
class ModernSaat {
constructor() {
this.saniye = 0;
}
baslat() {
// Ok
fonksiyonu üstteki baslat() metodunun 'this' değerini aynen
miras alır.
setInterval(() => {
this.saniye++;
console.log(this.saniye);
}, 1000);
}
}
Buraya kadar olan kısımda Nesne Yönelimli
Programlamanın modern detaylarını, yeni gelen kapsülleme yöntemlerini ve dilin
en kritik virajı olan this yapısını ele aldık.
Harika, kurallarımızı bozmadan süreleri dahil
etmeyerek, özet geçmeden, teorik altyapılar, kod örnekleri ve pratik
uygulamalarla satır satır ilerlemeye devam ediyoruz. Yarıda
kalırsam yine sizi bilgilendireceğim.
4. BÖLÜM: OOP
Under The Hood: Prototypes, New, & More!
(Perde Arkasında OOP: Prototipler, New ve Dahası!)
JavaScript'te diğer dillerdeki gibi gerçek
"klasik" sınıflar yoktur. Arka planda her şey nesneler ve onların
birbirine bağlandığı Prototip (Prototype)
mimarisiyle yürür. Sınıf (class) söz dizimi,
bu yapıyı gizleyen şık bir örtüdür.
OOP Under The Hood Intro
(Perde Arkasındaki OOP'ye Giriş)
JavaScript'te bir nesne oluşturduğumuzda, o nesne
durup dururken bazı metotlara (örneğin .toString() veya .hasOwnProperty()) sahip olur.
Bunun sebebi, nesnenin arka planda gizli bir "ata nesneye" bağlı
olmasıdır. İşte bu ata nesneye prototip denir.
The New Keyword (new Anahtar Kelimesinin Gizemi)
Bir fonksiyonun önüne new kelimesi
koyup çağırdığımızda sırasıyla şu gizli adımlar gerçekleşir:
Kod Örneği (Arka Planın Taklidi):
function Araba(marka) {
this.marka = marka;
}
// new
Araba("Toyota") dediğimizde arka planda yukarıdaki 4 adım işler.
const benimArabam = new Araba("Toyota");
console.log(benimArabam.marka); //
"Toyota"
Prototipler: Part 1, Part 2 & Part 3 (Derinlemesine Prototipler)
JavaScript'te her fonksiyon oluşturulduğunda,
otomatik olarak prototype adında boş bir nesne özelliğine sahip olur.
Kod Örneği:
function Oyuncu(isim, skor) {
this.isim = isim;
this.skor = skor;
}
// Metodu prototipe ekliyoruz
(Bellekte sadece 1 tane var)
Oyuncu.prototype.puanKazan = function() {
this.skor += 10;
console.log(`${this.isim} puan
kazandı! Yeni skor: ${this.skor}`);
};
const o1 = new Oyuncu("Ali", 50);
const o2 = new Oyuncu("Veli", 40);
o1.puanKazan(); // "Ali
puan kazandı! Yeni skor: 60"
o2.puanKazan(); // "Veli
puan kazandı! Yeni skor: 50"
// İkisi de aynı fonksiyon
referansını kullanır:
console.log(o1.puanKazan === o2.puanKazan); // true
The Prototype Chain (Prototip Zinciri)
Bir nesnenin bir özelliğine veya metoduna erişmek
istediğinizde, JavaScript motoru önce nesnenin kendi içine bakar. Bulamazsa
nesnenin prototipine (__proto__) bakar. Orada da bulamazsa prototipin
prototipine bakar. Bu arama zinciri null değerine
ulaşana kadar yukarı doğru devam eder. Buna Prototip Zinciri denir.
Görsel Akış Örneği:
o1 nesnesi -> Oyuncu.prototype -> Object.prototype -> null
Classes, Inheritance, & Prototypes (Sınıflar, Kalıtım ve Prototiplerin İlişkisi)
Modern JavaScript'te yazdığımız class ve extends yapıları,
yukarıda anlattığımız prototip zincirini otomatik olarak kuran birer araçtır. extends kullandığınızda, alt sınıfın prototipi üst
sınıfın prototipine zincirlenir.
__proto__ vs. prototype (En Çok
Karıştırılan İki Kavram)
Kod Örneği:
function Insan() {}
const can = new Insan();
// Nesnenin gizli bağı, fonksiyonun
kalıbına eşittir:
console.log(can.__proto__ === Insan.prototype); // true
Useful Prototype Methods (Faydalı Prototip Metotları)
Prototipleri sorgulamak ve güvenle yönetmek için
bazı yerleşik metotlar kullanılır.
Kod Örneği:
const canliMiras = {
nefesAl() {
console.log("Hava çekiliyor..."); }
};
// canliMiras'ı
doğrudan prototip alan yeni bir nesne kuruyoruz
const kedi = Object.create(canliMiras);
kedi.nefesAl(); // "Hava
çekiliyor..."
console.log(Object.getPrototypeOf(kedi) === canliMiras); // true
5. BÖLÜM: Asynchronous Code (Asenkron
Kodlama Dünyası)
JavaScript tek iş parçacıklı (single-threaded)
çalışan bir dildir; yani aynı anda sadece tek bir satır kod işleyebilir. Uzun
süren işlemlerin (örneğin internetten veri indirme, dosya okuma) tüm tarayıcıyı
veya sistemi kilitlemesini önlemek için Asenkron Mimari kullanılır.
Callbacks: Our
Good Friend (Geri Çağırma
Fonksiyonları)
Asenkron bir işlem bittiğinde çalıştırılmak üzere
başka bir fonksiyona parametre olarak geçilen fonksiyonlardır.
Kod Örneği:
console.log("1. Başladı");
// Asenkron zamanlayıcı (Simüle
edilmiş internet isteği)
setTimeout(function() {
console.log("2. Veri internetten geldi.");
}, 2000);
console.log("3. Bitti");
// Çıktı Sırası: 1. Başladı -> 3. Bitti -> (2 saniye sonra) 2. Veri
internetten geldi.
Callback Hell
& The Pyramid of Doom (Callback Cehennemi ve Yıkım
Piramidi)
Ardışık asenkron işlemler yapılması gerektiğinde
(örneğin: önce kullanıcıyı getir, sonra kullanıcının siparişlerini bul, sonra
siparişin detayını indir), callback fonksiyonları iç
içe girmeye başlar. Kod sağa doğru uzayarak okunamaz ve yönetilemez bir
piramide dönüşür.
Hatalı Tasarım Örneği (Cehennem):
kullaniciGetir(1, (kullanici) => {
siparisleriGetir(kullanici.id, (siparisler) => {
detayGetir(siparisler[0], (detay) => {
console.log(detay);
// Kod bu
şekilde sağa doğru çöker...
});
});
});
The Basics of Promises (Promise -
Söz Vermek - Temelleri)
Callback cehenneminden
kurtulmak için üretilen, gelecekte tamamlanacak (başarılı veya başarısız) bir
asenkron işlemin sonucunu temsil eden nesnedir. Bir Promise
3 durumdan birinde bulunur:
Using .then() and .catch() (Sonuçları Yakalamak)
Kod Örneği:
const veriGetir = new Promise((resolve, reject) => {
let basariliMi = true;
if (basariliMi) {
resolve("Harika veri yüklendi!");
} else {
reject("Bağlantı hatası oluştu.");
}
});
veriGetir
.then((sonuc) => console.log(sonuc)) // "Harika veri yüklendi!"
.catch((hata) => console.error(hata));
Promise Chaining To Flatten Code
(Kodu Düzleştirmek İçin Promise Zincirleme)
İç içe giren callback
yapısını alt alta temiz bir zincire dönüştürme tekniğidir. Her
.then() bloğu içerisinden yeni bir Promise döndürerek işlemler ardışık hale getirilir.
Kod Örneği:
// Callback
cehenneminin temiz çözümü:
kullaniciGetir(1)
.then(kullanici => siparisleriGetir(kullanici.id))
.then(siparisler => detayGetir(siparisler[0]))
.then(detay
=> console.log(detay))
.catch(hata
=> console.log("Adımlardan birinde hata
oldu:", hata));
Async/Await Basics & More on Async/Await
(Asenkron Kodun Zirvesi)
Asenkron kodları, sanki senkronmuş (düz,
yukarıdan aşağıya sırayla çalışan kodlar gibi) yazmamızı sağlayan muazzam bir
ES2017 özelliğidir. Arka planda yine Promise yapısını
kullanır.
Kod Örneği:
// Mock
(Simüle) veri fonksiyonu
function surekliIs() {
return new Promise(resolve
=> setTimeout(() => resolve("Veri"), 1000));
}
async function calistir() {
console.log("İşlem başlıyor...");
const sonuc = await surekliIs(); // 1 saniye
burada bekler, alt satıra geçmez.
console.log("Sonuç geldi:", sonuc);
}
calistir();
Error Handling With Async Functions (Async Fonksiyonlarda Hata Yönetimi)
Async/Await yapısında .catch() yerine geleneksel, okunması
çok kolay olan try-catch blokları kullanılır.
Kod Örneği:
async function guvenliVeriCek() {
try {
const veri = await internettenIstekAt();
console.log(veri);
} catch (hata) {
console.log("İstek sırasında hata yakalandı:", hata.message);
}
}
Async Patterns: Parallel vs. Sequential
Operations (Paralel ve Sıralı Operasyonlar)
Kod Örneği (Sıralı -
Yavaş Yöntem):
async function sirayla() {
const veri1 = await istek1(); // 2 saniye
sürsün
const veri2 = await istek2(); // 2 saniye
sürsün -> Toplam 4 saniye.
}
Async Patterns: Promise.all()
Birbirinden bağımsız birden fazla Promise işlemini aynı anda paralel olarak başlatan ve hepsi
başarıyla tamamlandığında toplu bir sonuç dizisi dönen metottur.
Kod Örneği:
async function paralelGorevler()
{
try {
// İki istek
aynı anda başlar
const [r1, r2] = await Promise.all([istek1(), istek2()]);
console.log("İki veri de başarıyla geldi:", r1, r2);
} catch (e) {
console.log("En az biri hatalı olduğu için sistem durdu.");
}
}
Async Patterns: Promise.allSettled()
Promise.all() gibidir, bağımsız istekleri
paralel yürütür. Ancak bazı istekler hata alsa bile süreci durdurmaz. Tüm
işlemler bittiğinde, hangisinin başarılı hangisinin başarısız olduğunu gösteren
detaylı bir durum raporu dizisi verir.
Kod Örneği:
const p1 = Promise.resolve("Başarılı
iş");
const p2 = Promise.reject("Hata
alan iş");
Promise.allSettled([p1,
p2]).then((sonuclar) => {
console.log(sonuclar);
/* Çıktı
dizisi:
[
{ status:
"fulfilled", value:
"Başarılı iş" },
{ status:
"rejected", reason:
"Hata alan iş" }
]
*/
});
Async Patterns: Promise.race()
Verilen Promise
listesindeki işlemlerden en hızlı olan hangisiyse (ister başarıyla
tamamlansın ister hata alsın) onun sonucunu kabul eden yarış mekanizmasıdır.
Kod Örneği (Zaman Aşımı -
Timeout Uygulaması):
const veriIstegi = internettenVeriCek();
const zamanAsimi = new Promise((_, reject) =>
setTimeout(() => reject(new Error("Bağlantı zaman aşımına uğradı!")), 5000)
);
// Hangisi daha hızlıysa o
kazanacak. 5 saniyede veri gelmezse hata fırlayacak.
Promise.race([veriIstegi, zamanAsimi])
.then(veri
=> console.log(veri))
.catch(hata
=> console.log(hata.message));
Building Our Own Promise Objects (Kendi Promise Nesnemizi İnşa Etmek)
Bir fonksiyonun asenkron desteği yoksa (eski
mimariler), onu new Promise içine sararak
modern hale getirebiliriz.
Uygulama Kodu (Gecikmeli Sayaç Uygulaması):
function beklemeSüresiVer(ms) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(`${ms} milisaniye süre doldu.`);
}, ms);
});
}
// Kullanımı
beklemeSüresiVer(1500).then(mesaj => console.log(mesaj)); // 1.5 saniye sonra basar
Promisifying Node's
fs.readFile() (NodeJS fs.readFile'ı Promise Yapısına Dönüştürmek)
Node.js'in eski dosya
okuma metotları Promise desteklemez, callback ile çalışır. Bunları Promise
uyumlu hale getirme işlemine Promisify denir.
Uygulama Kodu:
// Node.js ortamı simülasyonu
const fs = require('fs');
function dosyaOkuSözü(dosyaYolu) {
return new Promise((resolve, reject) => {
fs.readFile(dosyaYolu, 'utf8', (err, data) => {
if (err) {
reject(err); // Hata varsa
sözü boz
} else {
resolve(data);
// Başarılıysa veriyi gönder
}
});
});
}
// Artık harika bir şekilde async/await ile kullanabiliriz:
async function veriyiGoster() {
try {
const icerik = await dosyaOkuSözü("./metin.txt");
console.log(icerik);
} catch (hata) {
console.error("Dosya okunurken hata:", hata);
}
}
Bu aşamada JavaScript'in alt katmanlarındaki
prototip kalıtım yapısını çözdük ve modern web uygulamalarının kalbi olan
Asenkron mimariyi (Promise, Async/Await kalıpları) eksiksiz bitirdik.
Harika bir yol haritasıyla ilerliyoruz!
İstediğiniz kurallara harfiyen uyarak; zaman sürelerini dahil etmeden, hiçbir
konuyu özetlemeden, teorik altyapılar, kod örnekleri ve pratik uygulamalarla
anlatmaya devam ediyorum.
Ayrıca isteğiniz üzerine, bu iki yeni bölüme
geçmeden önce, bir önceki adımda öğrendiğimiz Prototip Kalıtımı ve Asenkron
Programlama (Promises/Async-Await)
kavramlarını harmanlayan kompleks ve gerçekçi bir proje uygulaması
geliştireceğiz.
Eğer içeriğin derinliğinden dolayı yarıda
kalırsam yine sizi bilgilendireceğim.
EK BÖLÜM:
Prototip ve Asenkron Mimari İle "Gelişmiş Görev
Dağıtım ve Takip Sistemi" (Kompleks Proje Uygulaması)
Bu projede, saf JavaScript kullanarak internetten
dinamik veri çeken, işçileri ve görevleri prototip tabanlı kalıtımla modelleyen
ve tüm süreçleri asenkron olarak paralel/sıralı yöneten bir sistem kuracağız.
//
==========================================
// 1. PROTOTİP TABANLI MODEL
TANIMLAMALARI
//
==========================================
// Ana Personel Kurucu Fonksiyonu
(Base Model)
function Personel(id, isim, rol) {
this.id = id;
this.isim = isim;
this.rol = rol;
this.aktifGorev Sayisi = 0;
}
// Personel prototipine ortak metot
ekliyoruz
Personel.prototype.bilgiVer = function() {
return `[ID: ${this.id}] ${this.isim} - Rol: ${this.rol}`;
};
// Alt Sınıf: Yazilimci
Kurucu Fonksiyonu (Inheritance)
function Yazilimci(id, isim, uzmanlikAlani) {
// Üst sınıfın
constructor'ını çağırıyoruz (super
benzeri yapı)
Personel.call(this, id, isim, "Yazılımcı");
this.uzmanlikAlani = uzmanlikAlani;
}
// Prototip zincirini kuruyoruz
(Kalıtımın kalbi)
Yazilimci.prototype = Object.create(Personel.prototype);
// Constructor
referansını düzeltiyoruz
Yazilimci.prototype.constructor = Yazilimci;
// Yazilimci
prototipine özel ek metot
Yazilimci.prototype.kodYaz = function(gorevAdi) {
console.log(`${this.isim}, ${this.uzmanlikAlani} kullanarak "${gorevAdi}" üzerinde çalışıyor...`);
};
//
==========================================
// 2. ASENKRON GÖREV YÖNETİM MOTORU
//
==========================================
const GorevMotoru = {
// İnternetten
simüle edilmiş görev verilerini çeken asenkron metot
async gorevleriGetir() {
console.log("Bulut sunucusundan görev listesi çekiliyor...");
return new Promise((resolve, reject) => {
setTimeout(() => {
const basariliMi = true; // Hata durumunu test etmek için false
yapılabilir
if (basariliMi) {
resolve([
{ id: 101, ad: "Veritabanı Optimizasyonu", sure: 1500, zorluk: "İleri" },
{ id: 102, ad: "API
Entegrasyonu", sure: 1000, zorluk: "Orta" },
{ id: 103, ad: "Arayüz
Yenilenmesi", sure: 2000, zorluk: "Kolay" }
]);
} else {
reject(new Error("Sunucu yanıt vermedi!"));
}
}, 1000);
});
},
// Görevi
asenkron olarak işçiye atayıp süreci takip eden metot
async goreviYurut(yazilimci, gorev) {
yazilimci.aktifGorev
Sayisi++;
console.log(`\n>>> BAŞLADI: "${gorev.ad}" görevi
${yazilimci.bilgiVer()} personeline atandı.`);
yazilimci.kodYaz(gorev.ad);
return new Promise((resolve) => {
setTimeout(() => {
yazilimci.aktifGorev
Sayisi--;
console.log(`<<< TAMAMLANDI: "${gorev.ad}" bitti.
(${gorev.sure}ms)`);
resolve({ gorevId: gorev.id, durum: "Başarılı", calisan: yazilimci.isim });
}, gorev.sure);
});
}
};
//
==========================================
// 3. SİSTEMİN PARALEL VE SIRALI
ÇALIŞTIRILMASI
//
==========================================
async function sistemiBaslat() {
try {
//
Nesnelerimizi prototip modelimizden üretiyoruz
const dev1 = new Yazilimci(1, "Ahmet Yılmaz", "Node.js & Veritabanı");
const dev2 = new Yazilimci(2, "Zeynep Kaya", "React & CSS");
// 1. Adım:
Verileri asenkron indir
const gorevListesi = await GorevMotoru.gorevleriGetir();
console.log(`${gorevListesi.length} adet görev başarıyla indirildi.`);
// 2. Adım:
Paralel Operasyon (Promise.all)
// İlk iki
görevi Ahmet ve Zeynep'e aynı anda verip paralel başlatıyoruz
console.log("\n--- PARALEL OPERASYON BAŞLIYOR ---");
const hamle1 = GorevMotoru.goreviYurut(dev1, gorevListesi[0]);
const hamle2 = GorevMotoru.goreviYurut(dev2, gorevListesi[1]);
const paralelSonuclar = await Promise.all([hamle1, hamle2]);
console.log("Paralel süreç raporu:", paralelSonuclar);
// 3. Adım:
Sıralı Operasyon (Sequential)
// Kalan son
görevi, önceki işlerin bitişine göre sıralı olarak dev1'e veriyoruz
console.log("\n--- SIRALI OPERASYON BAŞLIYOR ---");
const siraliSonuc = await GorevMotoru.goreviYurut(dev1, gorevListesi[2]);
console.log("Sıralı süreç raporu:", siraliSonuc);
console.log("\n[SİSTEM]: Tüm operasyonlar sıfır hata ile tamamlandı.");
} catch (hata) {
console.error("[SİSTEM HATASI]:", hata.message);
}
}
// Projeyi tetikliyoruz
sistemiBaslat();
6. BÖLÜM: Latest JavaScript Features
(Modern ES2021 & ES2022 Yenilikleri)
JavaScript sürekli gelişen bir dildir. ES2021 ve
ES2022 standartları, kod yazarken karşılaştığımız hamallıkları bitiren çok
güçlü söz dizimi çözümleri getirmiştir.
Optional Chaining
(İsteğe Bağlı Zincirleme - ?.)
Derin iç içe geçmiş nesne yapılarında, bir
özelliğin var olup olmadığını kontrol etmeden okumaya çalıştığımızda oluşan
ölümcül hataları engelleyen harika bir operatördür.
Kod Örneği:
const musteri = {
isim: "Can",
// adres
bilgisi internetten eksik gelmiş olsun
};
// Eski Yöntem (Uzun ve yorucu)
let sokakEski = musteri.adres && musteri.adres.sokak ? musteri.adres.sokak
: "Bilinmiyor";
// Yeni Yöntem (Temiz ve güvenli)
let sokakYeni = musteri.adres?.sokak;
console.log(sokakYeni); // undefined (Hata vermedi, program çökmedi!)
Nullish Coalescing (Boşluk
Birleştirme Operatörü - ??)
Bir değişkenin değeri null veya undefined olduğunda, onun yerine varsayılan (default) bir değer atamak için kullanılan operatördür.
Kod Örneği:
const ayarlar = {
animasyonHizi: 0, // Kullanıcı hızı özellikle 0 yapmak istemiş olsun.
};
// VEYA (||) kullanımı hataya yol
açar:
const hiz1 = ayarlar.animasyonHizi || 300;
console.log(hiz1);
// 300 (0'ı yok saydı, hatalı durum!)
// Nullish
Coalescing (??) doğru çalışır:
const hiz2 = ayarlar.animasyonHizi ?? 300;
console.log(hiz2);
// 0 (Çünkü 0 bir null veya undefined değildir, geçerlidir.)
Numeric Separators (Sayısal Ayırıcılar - _)
Çok büyük sayıları yazarken ve okurken gözden
kaçan basamak hatalarını engellemek amacıyla sayıların arasına alt çizgi (_) koyabilme özelliğidir.
Kod Örneği:
const bütçeEski = 1000000000; // Sıfırları
saymak çok zor.
const bütçeYeni = 1_000_000_000; // Okuması çok
kolay (1 Milyar).
console.log(bütçeYeni === bütçeEski); // true
Array.prototype.at()
Dizilerin ve metinlerin (string)
belirli bir indeksindeki elemanı getiren modern metottur. En büyük yeteneği negatif
indeks desteklemesidir.
Kod Örneği:
const renkler = ["Kırmızı", "Mavi", "Yeşil", "Sarı"];
// Son elemanı alma
console.log(renkler.at(-1)); //
"Sarı"
console.log(renkler.at(-2)); //
"Yeşil" (Sondan ikinci)
String replaceAll()
Bir metin içerisindeki belirtilen bir alt metnin tüm
eşleşmelerini yenisiyle değiştiren metottur.
Kod Örneği:
const mesaj = "elma suyu, elma püresi ve elma ağacı";
// Tüm elma kelimelerini armut
yapalım
const yeniMesaj = mesaj.replaceAll("elma", "armut");
console.log(yeniMesaj); // "armut
suyu, armut püresi ve armut ağacı"
Logical Assignment Operators (Mantıksal Atama Operatörleri -
||=, &&=, ??=)
Matematikteki x += 5 yapısının mantıksal operatörlere uyarlanmış
halidir. Kod satırlarını kısaltmada çok etkilidir.
Kod Örneği:
let u1 = "";
u1 ||= "Misafir"; //
"" falsy olduğu için atama gerçekleşir.
console.log(u1);
// "Misafir"
let u2 = "Ahmet";
u2 &&= "Aktif
Kullanıcı"; // "Ahmet" truthy olduğu için üstüne
yazar.
console.log(u2);
// "Aktif Kullanıcı"
let u3 = 0;
u3 ??= 100; // 0 null/undefined olmadığı için
atama YAPMAZ.
console.log(u3);
// 0
Promise.any()
Girdi olarak verilen Promise
listesinden başarıyla tamamlanan ilk Promise
sonucunu getiren metottur.
Kod Örneği:
const sunucuA = new Promise((_, reject) => setTimeout(() => reject("A çöktü"), 500));
const sunucuB = new Promise((resolve) => setTimeout(() => resolve("B'den veri geldi"), 1000));
// Sunucu A daha hızlı bitiyor ama
hatalı. any() onu geçer, başarılı olan B'yi bekler.
Promise.any([sunucuA, sunucuB])
.then(sonuc => console.log(sonuc)) // "B'den veri geldi"
.catch(hata
=> console.log("Hepsi çöktü"));
7. BÖLÜM: The Tricky Parts
of JavaScript (JavaScript'in Hileli ve Yanıltıcı Kısımları)
JavaScript alelacele (yaklaşık 10 günde)
tasarlanmış bir dil olduğu için mimarisinde inanılmaz mantık hataları ve
büyüleyici sürprizler barındırır. Mülakatlarda en çok sorulan ve kıdemli
yazılımcıların bile zaman zaman saç baş yolduğu alan burasıdır.
Working With Float Imprecision (Ondalıklı Sayı
Hassasiyeti Kusuru)
JavaScript dünyasındaki en büyük şoklardan biri 0.1 + 0.2 işleminin
sonucudur.
Kod Örneği:
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false!
let toplam = (0.1 * 10 + 0.2 * 10) / 10;
console.log(toplam === 0.3); // true
BigInt() and Really Large Numbers
(Gerçekten Büyük Sayılar)
JavaScript'in normal sayı türüyle güvenle
işleyebileceği en büyük tam sayı değeri 2^53 - 1'dir (9,007,199,254,740,991). Bu sayı
sınırına Number.MAX_SAFE_INTEGER denir. Bu
sınırdan sonra matematik çöker.
Kusur Örneği:
console.log(9007199254740991 + 1); // 9007199254740992
console.log(9007199254740991 + 2); // 9007199254740992 (Matematik bozuldu!)
const buyukSayi1 = 9007199254740991n;
console.log(buyukSayi1 + 2n); //
9007199254740993n (Doğru sonuç!)
isNaN() vs. Number.isNaN() (NaN Paradoksu)
NaN (Not a Number -
Bir Sayı Değil), matematiksel olarak geçersiz bir işlemin sonucunda üretilen
özel bir sayı tipidir. İşin tuhafı, NaN kendi kendine
bile eşit değildir!
Kusur Örneği:
console.log(NaN === NaN); // false! (Dünyadaki tek kendine eşit olmayan
değer)
console.log(isNaN("merhaba")); // true ("merhaba" sayıya çevrilemediği için true dedi, mantıksız)
console.log(Number.isNaN("merhaba")); // false (Çünkü "merhaba" bir string'dir,
NaN nesnesi değildir)
Post and Pre Increment
(++x vs. x++ Farkı)
Değişkeni 1 artırma operatörünün yerleşimi, kodun
çalışma önceliğini tamamen değiştirir.
Kod Örneği:
let a = 5;
let b = a++; // Önce b = 5 olur, sonra a = 6 olur.
console.log(a, b); // 6, 5
let x = 5;
let y = ++x; // Önce x = 6 olur, sonra y = 6 olur.
console.log(x, y); // 6, 6
Automatic Semicolon
Insertion (Otomatik Noktalı Virgül Ekleme
- ASI)
JavaScript motoru, geliştirici satır sonuna
noktalı virgül (;) koymasa bile kodu yorumlarken gizlice bu virgülleri ekler. Bu durum bazen
ölümcül mantık hatalarına neden olur.
Kusur Örneği:
function veriDon() {
return
{
durum: "Başarılı"
}
}
console.log(veriDon());
// undefined döner!
JavaScript Generator Functions (Üretici Fonksiyonlar - function*)
İstendiği zaman çalışması ortasında
durdurulabilen (duraklatılabilen) ve daha sonra kaldığı yerden devam
ettirilebilen çok özel fonksiyon türleridir.
Kod Örneği:
function* sayacUretici() {
console.log("Birinci aşama");
yield 1; // Burada fonksiyon donar!
console.log("İkinci aşama");
yield 2;
}
const generator = sayacUretici();
console.log(generator.next()); // "Birinci aşama" yazar ve { value: 1,
done: false } döner
console.log(generator.next()); // "İkinci aşama" yazar ve { value: 2,
done: false } döner
console.log(generator.next()); // { value: undefined,
done: true } (Bitti)
When Are Generators Useful? (Generator'lar Nerelerde Kullanışlıdır?)
Uygulama Kodu (Sonsuz Benzersiz ID Üretici):
function* idUretici() {
let id = 1;
while(true) { // Sonsuz
döngü normalde tarayıcıyı kilitler ama yield ile
güvenlidir.
yield `USER_ID_${id++}`;
}
}
const idFabrikasi = idUretici();
console.log(idFabrikasi.next().value); // "USER_ID_1"
console.log(idFabrikasi.next().value); // "USER_ID_2"
The Incredibly Versatile Array.from() Method (Çok Yönlü Array.from())
Dizi benzeri (Iterable
veya Array-like) nesneleri (örneğin HTML NodeList'leri, Set veya Map
yapılarını) gerçek bir JavaScript dizisine dönüştürmeyi sağlayan mucizevi
metottur. İkinci parametre olarak bir map fonksiyonu
alabilir.
Uygulama Kodu (Belli Bir Aralıkta
Sayı Dizisi Üretme):
// 1'den 5'e kadar sayı içeren
gerçek bir dizi oluşturma
const beslikDizi = Array.from({ length: 5 }, (eleman, indeks) => indeks + 1);
console.log(beslikDizi); //
Bu adımla birlikte modern dil yeteneklerini ve
motor seviyesindeki en tehlikeli hileli mantıkları derinlemesine öğrenmiş
olduk.
Metninizde yer alan tüm eğitim içeriğini ve
"Öğrenecekleriniz" bölümünü, istediğiniz kurallar doğrultusunda
(dakika/saniye bilgileri, "Önizleme"
yazıları ve "ders" satırları olmadan) satır satır
ele alarak çok detaylı bir şekilde açıklamaya başlıyorum. Konuların mantığını
tam olarak kavrayabilmeniz için her bölüme özel gerçek hayat benzetmeleri
(analojiler), kod örnekleri ve pratik uygulamalar ekledim.
Eğer anlatım sırasında yapay zeka
sistem sınırları nedeniyle yanıt yarıda kalırsa, kaldığım yeri size mutlaka
bildireceğim.
"Öğrenecekleriniz"
Bölümünün Detaylı Açıklaması
Bu kurs boyunca sadece teorik bilgi
öğrenmeyeceksiniz, aynı zamanda öğrendiklerinizi hayata geçireceksiniz. İşte bu
bölümde bahsedilen maddelerin tek tek açıklaması:
Kurs
İçeriğinin Satır Satır Ele Alınması ve Uygulamalar
Giriş Bölümü: Terminal Kullanımı ve İlk Kod
Terminal (Komut Satırı) Kullanımı
Terminal, bilgisayarınıza fareyle tıklayarak
değil, sadece yazılar yazarak emir verdiğiniz siyah bir ekrandır. Tıpkı eski
bilgisayarlardaki gibi, klasörlerin içinde gezinmeyi ve JavaScript
dosyalarımızı çalıştırmayı bu siyah ekran üzerinden yapacağız.
Hello JavaScript!
ve İlk Scripti Çalıştırmak
Bilgisayarımıza her şeyin doğru kurulduğunu
kanıtlamak için yazacağımız ilk küçük kod satırıdır.
console.log("Merhaba JavaScript Dünyası!");
Bölüm: JavaScript Temelleri -
Değişkenler ve Akış Kontrolü
Değişkenler ve String
(Metin) İfadeler
Değişken (Variable): Bilgisayarın
hafızasındaki etiketli kutulardır. İçine sayılar, yazılar koyarız ve üstüne bir
isim yazarız.
String: JavaScript'te tırnak işaretleri
içine yazılan her türlü düz metindir.
let kullaniciAdi = "Ahmet"; // kullaniciAdi isimli kutuya "Ahmet" metnini
koyduk.
let ad = "Can";
let soyad = "Yılmaz";
console.log(ad + " " + soyad); // Ekranda "Can Yılmaz" yazar.
Sayılar (Numbers) ve
Matematiksel İşlemler
JavaScript'te tam sayılar ve ondalıklı sayılar
doğrudan kullanılır. Toplama (+), çıkarma (-), çarpma (*) ve bölme (/) işlemleri yapabiliriz.
let urunFiyati = 100;
let kdvOrani = 0.20;
let toplamVergi = urunFiyati * kdvOrani;
console.log(toplamVergi); // Ekrana 20
yazar.
Değişken İsimlendirme Kuralları ve Tuzaklar
Değişkenlere isim verirken kafamıza göre
davranamayız. İsimler sayı ile başlayamaz, boşluk içeremez ve JavaScript'in
kendi özel kelimeleri (örneğin let, if) değişken ismi olamaz.
Uygulama: Sıcaklık Dönüştürücü (Fahrenheit'tan Celsius ve
Kelvin'e)
Öğrendiğimiz matematiksel işlemleri kullanarak
bir sıcaklık dönüşüm programı yapıyoruz.
let fahrenheit = 50; // Dönüştürmek
istediğimiz değer
let celsius = (fahrenheit - 32) * (5 / 9);
let kelvin = celsius + 273.15;
console.log(fahrenheit + "
Fahrenheit eşittir " + celsius + " Derece Celsius");
console.log(fahrenheit + "
Fahrenheit eşittir " + kelvin + "
Kelvin");
Boolean
(Doğru/Yanlış) ve Karşılaştırma Operatörleri
Boolean: Bir durumun
ya sadece true (Doğru) ya da false (Yanlış) olma
halidir. İki şeyi karşılaştırırken kullanılır.
let yas = 20;
let yetiskinMi = yas >= 18; // 20, 18'den
büyük veya eşit olduğu için true döner.
console.log(yetiskinMi); // true
If (Eğer) Şartlı
İfadeleri
Kodlarımızın bir şarta bağlı olarak çalışmasını
sağlar. Şart doğruysa o kod bloku çalışır, değilse pas geçilir.
let havaYagmurlu = true;
if (havaYagmurlu) {
console.log("Şemsiyeni yanına almayı unutma!");
}
Gelişmiş If İfadeleri
(Else ve Else If)
Sadece tek bir şart değil, birden fazla
alternatif durum olduğunda kullanılır.
let yas = 12;
if (yas < 6) {
console.log("Bilet ücretsiz.");
} else if (yas < 18)
{
console.log("Çocuk bileti tarifesi.");
} else {
console.log("Tam bilet tarifesi.");
}
Mantıksal "And"
(Ve) ve "Or" (Veya) Operatörleri
Birden fazla şartı birbirine bağlamak için
kullanılır.
let ehliyetVar = true;
let alkol Yok = true;
let arabaSürebilir = ehliyetVar && alkolYok; // İkisi de true ise sonuç true olur.
Değişken Kapsamı (Variable
Scope) - Bölüm I ve II
Scope (Kapsam): Bir
değişkenin kodun hangi bölgelerinde yaşayabildiğini ve nereden erişilebilir
olduğunu belirler. Süslü parantezlerin {} içi (blok) yerel kapsamdır, dışı ise küresel
(global) kapsamdır.
let isim = "Kaan"; // Küresel değişken
if (true) {
let isim = "Zeynep"; // Gölgeleme yapıldı, içeride artık Zeynep geçerli.
console.log(isim); // Zeynep
}
console.log(isim);
// Kaan (Dışarıdaki etkilenmedi)
Bölüm: JavaScript Fonksiyonları
Fonksiyon Temelleri (Function
Basics)
Fonksiyonlar, tekrar tekrar kullanabileceğimiz
kod paketleridir. Bir kere yazarız, canımız ne zaman isterse adını çağırarak
çalıştırırız.
function selamla() {
console.log("Merhaba değerli misafir!");
}
selamla(); // Fonksiyonu
çalıştırdık.
Undefined ve Null Kavramları
let puan;
console.log(puan);
// Ekranda "undefined"
yazar.
let sepet = null; // Sepet şu an
bomboş demektir.
Çoklu Argümanlar ve Varsayılan Değerler
Fonksiyonlara çalışırken kullanmaları için
dışarıdan malzemeler (parametreler) gönderebiliriz. Eğer kullanıcı bu malzemeyi
göndermeyi unutursa diye varsayılan (default) yedek
değerler belirleyebiliriz.
function toplamHesapla(fiyat, vergi = 0.18) {
return fiyat + (fiyat * vergi);
}
console.log(toplamHesapla(100)); // Vergi gönderilmediği için 0.18 kullanır. Result:
118
Fonksiyon Kapsamı (Function
Scope)
Bir fonksiyonun içinde tanımlanan değişkenler
sadece o fonksiyonun içinde yaşar, fonksiyon bittiğinde yok olurlar. Dışarıdan
onlara erişilemez.
Template Strings (Şablon Dizileri)
Metinlerin içine değişkenleri artı işareti (+) kullanmadan, çok daha kolay
ve temiz bir şekilde yerleştirme yöntemidir. Ters tırnak (`) işaretiyle yazılır.
let urun = "Kitap";
let fiyat = 45;
// Eski yöntem: "Bu " +
urun + " fiyatı: " + fiyat + " TL"
console.log(`Bu ${urun} fiyatı: ${fiyat} TL`); // Modern yöntem
Uygulama: Not Hesaplayıcı (Grade Calculator)
Öğrencinin aldığı puanı ve toplam puanı vererek
harf notunu bulan gelişmiş bir uygulama geliştiriyoruz.
function notHesapla(ogrenciPuani, toplamPuan) {
let yuzde = (ogrenciPuani / toplamPuan) * 100;
let harfNotu = "";
if (yuzde >= 90) { harfNotu = "A"; }
else if (yuzde >= 80) { harfNotu = "B"; }
else if (yuzde >= 70) { harfNotu = "C"; }
else { harfNotu = "F"; }
return `Öğrencinin
skoru: %${yuzde}. Alınan Harf Notu: ${harfNotu}`;
}
let sonuc = notHesapla(16, 20);
console.log(sonuc); // %80 başarı ile B notu basar.
Bölüm: JavaScript Objeleri (Objects)
Obje Temelleri (Object Basics)
Objeler, birbiriyle ilişkili özellikleri tek bir
pakette toplamaya yarar. Süslü parantez kullanarak oluşturulurlar ve içlerinde
"anahtar: değer" çiftleri barındırırlar.
let kitap = {
isim: "Görünmez Adam",
yazar: "H.G. Wells",
sayfaSayisi: 250
};
console.log(kitap.isim); // Kitabın ismini okuduk: "Görünmez Adam"
Objeleri Fonksiyonlarla Kullanmak ve Obje
Referansları
Bir objeyi fonksiyona parametre olarak
gönderebiliriz veya bir fonksiyondan dışarıya yeni bir obje çıkartabiliriz.
JavaScript'te objeler "referans" ile taşınır; yani bir fonksiyonun
içinde objeyi değiştirirseniz, orijinal obje de değişir.
let hesap = { isim: "Can", bakiye: 500 };
function paraEkle(hesapNesnesi, miktar) {
hesapNesnesi.bakiye
+= miktar; // Orijinal hesabı doğrudan
etkiler!
}
paraEkle(hesap, 150);
console.log(hesap.bakiye); // 650
Uygulama: Gider Takip Programı (Expense Tracker)
Kişinin gelir ve giderlerini tutan bir sistem
kuruyoruz.
let benimGiderlerim = {
gelir: 0,
gider: 0
};
function gelirEkle(hesap, miktar) {
hesap.gelir
+= miktar;
}
function giderEkle(hesap, miktar) {
hesap.gider
+= miktar;
}
function özetiGoster(hesap) {
let kalan = hesap.gelir - hesap.gider;
return `Toplam Gelir:
${hesap.gelir} TL, Toplam Gider: ${hesap.gider} TL. Kalan
Bakiye: ${kalan} TL.`;
}
gelirEkle(benimGiderlerim, 2000);
giderEkle(benimGiderlerim, 450);
console.log(özetiGoster(benimGiderlerim));
Metotlar (Methods)
Bir objenin içerisine sadece yazı veya sayı
değil, fonksiyon da koyabilirsiniz. Objenin içindeki bu fonksiyonlara Metot
denir. Obje kendi içindeki verilere this kelimesiyle
ulaşır.
let uye = {
ad: "Mert",
merhabaDe: function() {
return `Merhaba, ben
${this.ad}`; // this, uye nesnesini temsil eder.
}
};
console.log(uye.merhabaDe());
Yerleşik String ve Number Metotları
JavaScript dilinin kendisinde otomatik olarak var
olan, işlerimizi kolaylaştıran hazır fonksiyonlardır.
let parola = "123456abc";
console.log(parola.length); // 9 karakter olduğunu söyler.
let piSajisi = 3.14159;
console.log(piSajisi.toFixed(2)); //
"3.14" yapar.
Sabit Değişkenler (Const)
ve Var Kelimesi
Bölüm: JavaScript Dizileri (Arrays)
Dizi Temelleri (Array
Basics)
Diziler, köşeli parantez [] kullanarak tek bir değişken
içinde birden fazla elemanı (liste şeklinde) saklamamızı sağlar. Listenin ilk
elemanı her zaman 0'ıncı indeksten başlar.
let alisverisListesi = ["Süt", "Ekmek", "Yumurta"];
console.log(alisverisListesi[0]); // Listenin ilk elemanı: "Süt"
Dizileri Metotlarla Değiştirmek
Dizilere yeni eleman eklemek veya mevcut
elemanları silmek için hazır araçlar kullanırız.
let arabalar = ["BMW", "Audi"];
arabalar.push("Fiat"); //
["BMW", "Audi", "Fiat"] oldu.
Diziler Üzerinde Döngü Kurmak (ForEach ve For Döngüsü)
Listenin içindeki tüm elemanları tek tek sırayla
bilgisayara inceletmek ve işlem yapmak için döngüleri kullanırız.
let skorlar =;
for (let i = 0; i < skorlar.length;
i++) {
console.log(`Skor: ${skorlar[i]}`);
}
Dizilerde Arama, Filtreleme ve Sıralama (Search, Filter, Sort)
let yaslar =;
let yetiskinler = yaslar.filter(function(yas) {
return yas >= 18;
});
console.log(yetiskinler); // [25, 30]
Bölüm: Tarayıcıda JavaScript (JavaScript in the Browser)
Web Sunucusu Kurmak ve HTML Bağlantısı
Kodlarımızın sadece terminalde değil, internet
tarayıcısında (Chrome, Edge vb.) çalışabilmesi için
yerel bir web sunucusu kurmayı ve yazdığımız JavaScript dosyasını bir HTML
dosyasının içine <script src="app.js"></script> kodu ile bağlamayı öğreniyoruz.
DOM Manipülasyonu (Document
Object Model)
DOM (Belge Nesne Modeli): HTML
sayfanızdaki her bir yazının, butonun veya resmin JavaScript tarafından kontrol
edilebilir birer nesneye dönüşmüş halidir. DOM sayesinde web sayfasındaki
yazıları dinamik olarak değiştirebiliriz.
document.querySelector('h1').textContent = "Yeni Başlık!";
Sayfaya DOM ile Yeni Elemanlar Eklemek
Boş bir HTML sayfamız olsa bile, JavaScript
kullanarak sayfada sıfırdan butonlar, paragraflar veya listeler yaratıp bunları
ekrana basabiliriz.
let yeniParagraf = document.createElement('p');
yeniParagraf.textContent = "Bu kodla eklenen bir
paragraftır.";
document.querySelector('body').appendChild(yeniParagraf);
Kullanıcı Etkileşimini Yakalamak (Event Listeners)
Kullanıcının web sitesi üzerinde yaptığı tıklama,
klavyeden bir tuşa basma veya fareyi hareket ettirme gibi olayları (Event) dinleyip anında tepki verme işlemidir.
let buton = document.querySelector('#bton-gonder');
buton.addEventListener('click', function() {
alert("Butona başarıyla
tıklandı!");
});
Formlar, Metin Girişleri (Inputs),
Checkbox ve Dropdown
Seçimleri
Bölüm: Veri Depolama, Kütüphaneler ve Ötesi
Verileri LocalStorage
İçinde Saklamak
Tarayıcı kapatılsa veya bilgisayar yeniden
başlatılsa bile yazdığımız notların veya yapılacaklar listesinin kaybolmamasını
sağlar. Verileri tarayıcının hafızasına kaydeder (CRUD işlemleri: Oluştur, Oku,
Güncelle, Sil).
localStorage.setItem('kullaniciAdi', 'Hakan'); // Kaydetme
let isim = localStorage.getItem('kullaniciAdi'); // Geri okuma
Kodları Dosyalara Bölmek ve Hata Ayıklama (Refactoring & Debugging)
Bütün kodları tek bir devasa dosyaya yazmak
yerine, işlevlerine göre küçük dosyalara bölerek temizlik yapıyoruz.
Geliştirici araçlarını (Developer Tools) kullanarak kodumuz nerede tıkanmış
adım adım izliyoruz.
Üçüncü Parti Kütüphaneler ve UUID Kullanımı
Çoklu Sayfalar Arası İletişim ve Veri
Senkronizasyonu
Ana sayfada bir nota tıkladığımızda, o notun ID
bilgisini adres çubuğundan (?id=123) diğer sayfaya aktarmayı ve iki farklı sekmede
açık olan sayfaların birbirini anlık olarak güncellemesini (Storage Event) öğreniyoruz.
JavaScript ile Tarih Saat İşlemleri ve Moment.js
JavaScript'in kendi tarih sistemi (new Date()) biraz
karmaşık ve kullanımı zordur. Bunun yerine tarihleri "2 gün önce
yazıldı", "10 dakika önce güncellendi" gibi insan diline kolayca
çevirebilen Moment.js kütüphanesini uygulamalarımıza entegre ediyoruz.
Bölüm: JavaScript Bilgimizi Genişletmek
Arrow Functions (Ok Fonksiyonları)
Klasik fonksiyon yazım tarzını çok daha kısa,
modern ve temiz hale getiren yeni söz dizimidir.
// Eski Yöntem
let kareAlEski = function(x) { return x * x; };
// Yeni Arrow
Yöntemi
let kareAlYeni = (x) => x * x;
Conditional Ternary Operator (Üçlü Şart
Operatörü)
Basit if / else kalıplarını
tek bir satırda yazmamızı sağlayan pratik bir kısaltmadır.
let yas = 20;
let mesaj = yas >= 18 ? "Giriş Serbest" : "Giriş Yasak";
// Soru işaretinden öncesi şarttır.
Doğruysa ilk kısım, yanlışsa iki noktadan sonrası çalışır.
Truthy ve Falsy Değerler ile Tür Dayatması (Type
Coercion)
Hata Fırlatmak ve Yakalamak (Try
/ Catch / Throw)
Programımızın beklenmedik bir hata yüzünden
tamamen çökmesini engeller. Riskli kodları bir güvenlik çemberine alırız.
try {
// Riskli
kodlar buraya yazılır
let veri = JSON.parse("Hatalı
Veri Formatı");
} catch (hata) {
// Hata olursa
program çökmez, burası çalışır
console.log("Bir hata oluştu ama sistem çalışmaya devam ediyor!");
}
Strict Mode (Sıkı Mod)
Kod dosyamızın en başına "use
strict"; yazarak aktif ederiz. JavaScript'in normalde göz
yumduğu bazı tehlikeli ve hatalı kod yazım alışkanlıklarını yasaklar ve hata
vermesini sağlar, böylece daha kaliteli kod yazarız.
Bölüm: Gelişmiş Objeler ve Fonksiyonlar (Nesne
Yönelimli Programlama)
Object Oriented
Programming (OOP) ve Prototip Mirası
OOP (Nesne Yönelimli Programlama): Kodlarımızı
gerçek dünyadaki nesnelere benzeterek inşa etme sanatıdır.
Prototypal Inheritance:
JavaScript'te bir objenin, başka bir objenin özelliklerini ve metotlarını miras
alarak kullanabilmesi altyapısıdır. Bu sayede hafızada boşuna yer kaplanmaz.
Yapıcı Fonksiyonlar (Constructor
Functions) ve Class Söz Dizimi
Aynı şablona sahip yüzlerce nesneyi tek bir
fabrikadan kolayca üretmemizi sağlar. Modern JavaScript ile gelen class yapısı bu üretimi çok daha şık yapmamızı sağlar.
class Oyuncu {
constructor(isim, skor) {
this.isim = isim;
this.skor = skor;
}
skorArttir() { this.skor++; }
}
let oyuncu1 = new Oyuncu("Can", 10); // Yeni bir
oyuncu üretildi
Alt Sınıflar (Subclasses)
Geliştirmek
Mevcut bir ana sınıftan türeyen ve onun tüm
özelliklerini miras alan daha özel alt sınıflar yaratmaktır.
Getters ve Setters (Alıcılar ve Ayarlayıcılar)
Bir objenin içindeki verilere doğrudan ulaşmak
yerine, araya bir güvenlik kontrolü koyarak veriyi okuma (get) veya veriyi değiştirme (set) işlemleridir.
Uygulama: Adam Asmaca Oyunu (Hangman)
Bu bölümde öğrendiğimiz tüm Nesne Yönelimli
Programlama ve sınıf (class) yapılarını
harmanlayarak, harf tahminlerine dayalı, kalan hakları hesaplayan çalışan bir
Adam Asmaca oyunu motoru inşa ediyoruz.
Bölüm: Asenkron JavaScript (Asynchronous
JavaScript)
HTTP İstekleri (Requests)
ve API Kavramı
Kendi bilgisayarımızdan çıkıp internet
aracılığıyla başka bir sunucuya bağlanarak oradan veri çekme işlemidir. Örneğin
Adam Asmaca oyunumuz için internetteki bir kelime sunucusundan rastgele
kelimeler talep ederiz.
Asenkron ve Senkron Çalışma Farkı
Callback Fonksiyonları
ve Closures
Promises (Vaatler) ve Promise Chaining
Asenkron işlemleri yönetmek için callback yapısının yerine gelen modern bir sistemdir. Bir
işlemin gelecekte olumlu (resolve) veya olumsuz
(reject) sonuçlanacağına dair bir söz (vaat) verir.
Zincirleme (then().then()) yapısı
sayesinde ardı ardına asenkron işlemler yapılabilir.
Fetch API ve Async / Await Yapısı
async function veriGetir() {
let cevap = await fetch('https://ornek.com');
let veri = await cevap.json();
console.log(veri);
}
Bölüm: Uygulama Temaları ve Canlıya Alma (App Themes)
CSS ile Görsel Giydirme
Şu ana kadar yaptığımız uygulamalar sadece düz
yazılardan ibaretti. Bu bölümde CSS (Stil Sayfaları) kullanarak
uygulamalarımıza renkler, modern buton tasarımları, hizalamalar ve harika arka
planlar ekleyerek göze hitap eden temalar hazırlıyoruz.
Hosting (Uygulamaları
İnternette Yayınlama)
Yaptığımız projeleri tüm dünyaya gösterme zamanı.
Kodlarımızı ücretsiz bir hosting servisinin
sunucularına yükleyerek, herkesin telefonundan veya bilgisayarından
girebileceği canlı bir web sitesi linki alıyoruz.
Bölüm: Babel ve Webpack ile İleri Düzey JavaScript
Tarayıcı Uumluluğu
Problemi ve Babel Çözümü
Yazdığımız en modern JavaScript kodları
(ES6/ES7), bazı eski internet tarayıcılarında çalışmayabilir ve web sitemiz o
tarayıcılarda çökebilir. Babel, bizim
yazdığımız modern kodları otomatik olarak tarayıp, tüm eski tarayıcıların
anlayabileceği eski nesil güvenli kodlara dönüştüren bir derleyicidir.
Webpack ve Modül
Sistemi
Projeler büyüdükçe onlarca JavaScript dosyamız
olur. Tarayıcının bu onlarca dosyayı tek tek yüklemesi performansı düşürür. Webpack, tüm bu farklı dosyaları ve kütüphaneleri
tarayıp tek bir optimize edilmiş akıllı dosya haline getiren (paketleyen)
harika bir araçtır. Modül sistemi sayesinde import ve export kelimelerini kullanarak dosyalar arası kod
paylaşırız.
Webpack Geliştirici
Sunucusu ve Kaynak Haritaları (Source Maps)
Modern Operatörler: Rest, Spread ve Destructuring
let kisi = { ad: "Selin", yas: 24 };
const { ad, yas } = kisi; // Tek satırda
ad ve yas değişkenleri oluşturuldu.
console.log(ad);
// Selin
Harika bir karar! JavaScript dünyasında
ustalaşmanın en kesin yolu, teoride kalan bilgileri bu tarz projelerle parmak
uçlarınıza dökmektir. İstediğiniz gibi Sıcaklık Dönüştürücü, Gider
Takip Programı ve Adam Asmaca uygulamalarını en temel seviyeden
ileri seviyeye doğru, hiçbir şeyi atlamadan, adım adım ve sıfırdan yazıyoruz.
Her projenin mantığını anlamanız için önce senaryoyu,
ardından kullanacağımız araçları ve son olarak satır satır açıklamalı kodlarını bulacaksınız.
1. Uygulama:
Sıcaklık Dönüştürücü (Temel Seviye)
Bu projede JavaScript'in en temel yapı taşları
olan değişkenleri, matematiksel operatörleri ve şablon
dizilerini (template strings)
pekiştireceğiz.
Kod Bloğu:
// 1. Adım: Başlangıç değerimizi
sabit bir değişkende tutuyoruz.
const fahrenheit Değeri = 50;
// 2. Adım: Fahrenheit'ı Celsius'a çeviren matematiksel formülü uyguluyoruz.
// Formül: (Fahrenheit
- 32) çarpı (5bölü9)
let celsiusDeğeri = (fahrenheitDeğeri - 32) * (5 / 9);
// 3. Adım: Celsius
değerini kullanarak Kelvin değerini hesaplıyoruz.
// Formül: Celsius
+ 273.15
let kelvinDeğeri = celsiusDeğeri + 273.15;
// 4. Adım: Sonuçları konsola
şablon dizileri (Template Strings)
ile yazdırıyoruz.
console.log("=== SICAKLIK DÖNÜŞÜM RAPORU ===");
console.log(`${fahrenheitDeğeri}°F derecesinin Celsius karşılığı: ${celsiusDeğeri}°C`);
console.log(`${fahrenheitDeğeri}°F derecesinin Kelvin karşılığı: ${kelvinDeğeri} K`);
2. Uygulama:
Gider Takip Programı (Orta Seviye)
Bu projede verileri bir arada tutmayı sağlayan objeleri,
işleri otomatikleştiren fonksiyonları ve objelerin kendi içindeki
verilere ulaşmasını sağlayan metot (this)
kavramını pekiştireceğiz.
Kod Bloğu:
// 1. Adım: Kullanıcının finansal
durumunu tutan ana objemizi oluşturuyoruz.
let cüzdan = {
sahibi: "Ahmet Yılmaz",
gelir: 0,
gider: 0,
// Objenin
kendi içinde çalışan ve özet çıkaran bir metot (fonksiyon) ekliyoruz.
özetiGöster: function() {
// Kalan
parayı anlık olarak hesaplıyoruz.
let netBakiye = this.gelir - this.gider;
console.log(`--- ${this.sahibi} Finansal
Özeti ---`);
console.log(`Toplam Kazanılan: ${this.gelir} TL`);
console.log(`Toplam Harcanan: ${this.gider} TL`);
console.log(`Cüzdanda Kalan Net Nakit: ${netBakiye} TL`);
console.log("-------------------------------------");
}
};
// 2. Adım: Cüzdana gelir ekleyen
bağımsız bir fonksiyon yazıyoruz.
// Bu fonksiyon parametre olarak
bir cüzdan objesi ve eklenecek miktarı alır.
function gelirEkle(cüzdanNesnesi, miktar) {
cüzdanNesnesi.gelir
+= miktar;
console.log(`+ Hesaba ${miktar} TL gelir eklendi.`);
}
// 3. Adım: Cüzdandan harcama yapan
bağımsız bir fonksiyon yazıyoruz.
function giderEkle(cüzdanNesnesi, miktar) {
cüzdanNesnesi.gider
+= miktar;
console.log(`- Hesaptan ${miktar} TL harcama yapıldı.`);
}
// 4. Adım: Sistemi yukarıdan
aşağıya çalıştırarak test ediyoruz.
gelirEkle(cüzdan, 15000); // Maaş yattı
giderEkle(cüzdan, 3500); // Kira ödendi
giderEkle(cüzdan, 1200); // Market alışverişi yapıldı
gelirEkle(cüzdan, 2500); // Ek işten para geldi
// 5. Adım: Objenin kendi içindeki
metodu çağırarak son durumu görüyoruz.
cüzdan.özetiGöster();
3. Uygulama:
Adam Asmaca Oyunu (İleri Seviye - Nesne Yönelimli)
Bu projede modern JavaScript'in en güçlü yanları
olan Sınıf (Class) yapısını, dizileri (Arrays),
dizi döngülerini (forEach, map)
ve kullanıcı girdilerini kontrol etme mantığını pekiştireceğiz. Tarayıcı
veya terminal üzerinden harf tahminleri yaparak kelimeyi bulmaya çalışacağız.
Kod Bloğu:
// 1. Adım: Oyunun tüm kurallarını
ve hafızasını yönetecek olan Sınıfı (Class) kuruyoruz.
class AdamAsmaca {
// Oyun ilk
başladığında kelimeyi ve can sayısını ayarlayan yapıcı motor.
constructor(gizliKelime, toplamCan) {
// Kelimeyi
büyük harflere çevirip harf harf bir diziye
bölüyoruz.
// Örn: "Kedi" -> ['K',
'E', 'D', 'I']
this.kelimeDizisi = gizliKelime.toUpperCase().split('');
this.kalanCan = toplamCan;
this.yapılanTahminler = []; // Oyuncunun
bastığı tüm harfler burada birikecek.
this.oyunDurumu = "DEVAM_EDIYOR"; //
"KAZANDI", "KAYBETTİ", "DEVAM_EDIYOR"
}
// 2. Adım:
Kelimenin ekranda görünen halini hesaplayan metot.
// Bilinen
harfleri gösterir, bilinmeyenlerin yerine alt çizgi (_) koyar.
bilmeceyiGörüntüle() {
// map metodu dizideki her harfi tek tek inceler ve
dönüştürür.
let gösterilecekHali = this.kelimeDizisi.map((harf) => {
// Eğer harf oyuncunun tahmin ettiği harflerin içinde varsa harfi göster
if (this.yapılanTahminler.includes(harf)) {
return harf;
} else {
// Yoksa oyuncu henüz bulamamıştır, alt çizgi göster
return "_";
}
});
// Diziyi yan
yana birleştirip düzgün bir yazı haline getiriyoruz.
return gösterilecekHali.join(' ');
}
// 3. Adım:
Oyuncunun harf tahminini işleyen ana metot.
tahminYap(harf) {
let tahmin = harf.toUpperCase();
// Eğer oyun
zaten bittiyse daha fazla tahmin yapılmasını engelle
if (this.oyunDurumu !== "DEVAM_EDIYOR") {
console.log("Oyun zaten bitti! Yeni oyun açın.");
return;
}
// Oyuncu aynı
harfi zaten daha önce tahmin ettiyse uyar
if (this.yapılanTahminler.includes(tahmin)) {
console.log(`'${tahmin}' harfini zaten denemiştiniz!`);
return;
}
// Yeni harfi
geçmiş tahminler listesine ekle
this.yapılanTahminler.push(tahmin);
// Eğer tahmin
edilen harf kelimenin içinde YOKSA canını bir azalt
if (!this.kelimeDizisi.includes(tahmin)) {
this.kalanCan--;
console.log(`Yanlış tahmin! '${tahmin}' kelimede yok. Kalan canınız: ${this.kalanCan}`);
} else {
console.log(`Tebrikler! '${tahmin}' harfi kelimede var.`);
}
// Her
tahminden sonra oyunun bitip bitmediğini kontrol et
this.durumuGüncelle();
}
// 4. Adım:
Oyunun kazanılma veya kaybedilme durumunu kontrol eden metot.
durumuGüncelle() {
// Durum 1:
Can bittiyse kaybetmiştir
if (this.kalanCan <= 0) {
this.oyunDurumu = "KAYBETTİ";
} else {
// Durum 2: Kelimedeki tüm harfler tahminlerin içinde var mı?
// every metodu "her eleman bu kurala uyuyor
mu" diye bakar.
let hepsiniBildimi = this.kelimeDizisi.every((harf) => {
return this.yapılanTahminler.includes(harf);
});
if (hepsiniBildimi) {
this.oyunDurumu = "KAZANDI";
}
}
// Sonucu
ekrana yazdır
this.sonucuYazdır();
}
// 5. Adım:
Oyuncuya anlık bilgi veren metot.
sonucuYazdır() {
console.log(`Kelime: ${this.bilmeceyiGörüntüle()}`);
if (this.oyunDurumu === "KAZANDI") {
console.log("🎉 TEBRİKLER! Kelimeyi doğru bildiniz
ve oyunu kazandınız! 🎉");
} else if (this.oyunDurumu === "KAYBETTİ") {
console.log(`💥 OYUN BİTTİ! Canınız tükendi. Doğru
kelime: ${this.kelimeDizisi.join('')} idi.`);
} else {
console.log("-----------------------------------------");
}
}
}
// === OYUNU SIFIRDAN BAŞLATMA VE
TEST ETME ===
// "NODEJS" kelimesiyle 3
canı olan bir oyun fabrikası kuruyoruz.
const yeniOyun = new AdamAsmaca("NODEJS", 3);
// İlk başta kelime tamamen kapalı
görünecek
console.log("--- ADAM ASMACA OYUNU BAŞLADI ---");
console.log(`Kelime: ${yeniOyun.bilmeceyiGörüntüle()}`);
console.log("-----------------------------------------");
// Oyuncu tahminler yapmaya
başlıyor:
yeniOyun.tahminYap("o"); // Doğru tahmin
yeniOyun.tahminYap("a"); // Yanlış tahmin (Can 2'ye düşer)
yeniOyun.tahminYap("n"); // Doğru tahmin
yeniOyun.tahminYap("x"); // Yanlış tahmin (Can 1'e düşer)
yeniOyun.tahminYap("d"); // Doğru tahmin
yeniOyun.tahminYap("e"); // Doğru tahmin
yeniOyun.tahminYap("j"); // Doğru tahmin
yeniOyun.tahminYap("s"); // Son doğru tahmin ve Kazanma!