Bu kurs, hiç bilmeyen birini ileri seviye bir JavaScript geliştiricisi yapmayı hedefler. Sadece kod yazmayı değil, arka planda nelerin döndüğünü ve bir yazılımcı gibi nasıl problem çözüleceğini öğretir.
Sıfırdan ileri seviye, kendine güvenen ve modern bir JavaScript geliştiricisi olmak: Dilin en eski yapılarından en modern ES6+ özelliklerine kadar her şeyi öğrenerek tarayıcıda veya sunucuda kod yazabilir hale geleceksiniz.
Portföyünüz için 6 adet harika gerçek dünya projesi inşa etmek: Sıkıcı ve sadece konsola yazı yazdıran uygulamalar yerine; insanların gerçekten kullanabileceği görsel, dinamik ve modern web uygulamaları yapacaksınız.
JavaScript'in perde arkasını anlayarak işe hazır hale gelmek: Kodunuzun bilgisayar hafızasında nasıl tutulduğunu, tarayıcının bu kodu nasıl çalıştırdığını öğrenerek mülakatlarda öne geçeceksiniz.
Bir geliştirici gibi düşünmek ve çalışmak: Karşılaştığınız bir hatayı Google, StackOverflow veya MDN (Mozilla Developer Network) kullanarak nasıl çözeceğinizi ve iş akışınızı nasıl yöneteceğinizi öğreneceksiniz.
JavaScript Temelleri: Veri saklamak, kararlar vermek, kodları tekrar oynatmak için gerekli olan tüm temel araçları (değişkenler, döngüler, fonksiyonlar, nesneler) kazanacaksınız.
Başlangıçtan itibaren Modern ES6+ dünyası: Kodları daha kısa ve okunabilir yazmamızı sağlayan ok fonksiyonları, dizileri parçalama ve yayma operatörleri gibi modern yetenekleri öğreneceksiniz.
Modern Nesne Yönelimli Programlama (OOP): Sınıflar ve yapıcı metotlar kullanarak düzenli, tekrar kullanılabilir ve güvenli kod yapıları kuracaksınız.
Karmaşık kavramlar (this, higher-order functions, closures): Çoğu geliştiricinin kafasını karıştıran, JavaScript'in en güçlü ve özel fonksiyon yeteneklerini tamamen çözeceksiniz.
Asenkron JavaScript (Event loop, promises, async/await, AJAX ve API'ler): İnternetten veri çekmek, arka planda işlemler yapmak ve sayfa donmadan akıcı uygulamalar sunmak için bu yapıları öğreneceksiniz.
Akış şemaları ve ortak kalıplar kullanarak kod mimarisi tasarlamak: Kod yazmaya başlamadan önce projenin planını yapmayı ve büyük projeleri yönetmeyi öğreneceksiniz.
Modern Araçlar (NPM, Parcel, Babel ve ES6 modülleri): Gerçek şirketlerde kullanılan paket yöneticilerini ve kod dönüştürücü araçları kullanmayı öğreneceksiniz.
50'den fazla pratik meydan okuma ve ödev: Sadece izlemekle kalmayıp, çözümlü ödevlerle teorik bilginizi pratiğe dökeceksiniz.
Soru-Cevap alanında hızlı destek: Takıldığınız her yerde topluluktan ve eğitmenden yardım alacaksınız.
Kurs haritaları: Kendi kariyer hedefinize göre hangi bölümleri hangi sırayla izlemeniz gerektiğini seçeceksiniz.
Bu bölümde programlamanın en temel taşları ve JavaScript'in tarayıcı ile ilk teması işlenir.
JavaScript, web sayfalarına canlılık ve etkileşim katan bir programlama dilidir. İlk olarak tarayıcının konsoluna bir yazı yazdırarak dünyaya merhaba deriz.
Örnek: Tarayıcı ekranında sağ tıklayıp "İncele" (Inspect) dedikten sonra "Konsol" (Console) sekmesine gidip kod yazarız.
Uygulama:
console.log("Hello World!");// Konsolda 'Hello World!' yazısı görünür.
JavaScript kodları HTML dosyasına
iki şekilde eklenebilir: Doğrudan HTML içine yazarak ya da
dışarıdaki bir .js
dosyasını bağlayarak. Gerçek projelerde kodların düzenli olması
için dış dosya tercih edilir.
Uygulama: Bir tane index.html
bir tane de script.js
dosyası açın. HTML dosyasının en altına şu kodu ekleyin:
<script src="script.js"></script>Değer, program içindeki en küçük bilgi parçasıdır (Örn: "Ahmet" veya 25). Değişkenler ise bu değerleri içinde sakladığımız etiketli kutulardır.
Örnek: Bir kişinin ismini hafızada tutmak.
Uygulama:
letfirstName="Ahmet";console.log(firstName);// Ahmet yazdırır.
JavaScript'te değerlerin türleri vardır. En temel olanlar: Number (Sayı), String (Yazı), Boolean (Doğru/Yanlış), Undefined (Tanımlanmamış) ve Null (Boş). JavaScript "dinamik tipli" bir dildir, yani bir değişkenin türünü belirtmeniz gerekmez, sistem bunu değerden anlar.
Uygulama:
letage=30;// Numberletname="Zeynep";// StringletisCodingFun=true;// Booleanletgrandchildren;// Undefined (Değer verilmedi)
let:
Değeri daha sonra değiştirilebilen değişkenler için
kullanılır.
const:
Değeri asla değiştirilemeyen (sabit) değişkenler için
kullanılır.
var:
Eski JavaScript sürümünden kalmadır, modern kodda güvenlik
nedeniyle tercih edilmez.
Uygulama:
letpoints=10;points =20;// Bu çalışır.constbirthYear=1995;// birthYear = 2000; -> HATA verir, sabit değiştirilemez.
Matematiksel (+, -, *, /) ve karşılaştırma (>, <, >=, <=) işlemlerini yapmamızı sağlar. Matematikteki gibi işlemler belirli bir öncelik sırasına göre yapılır.
Uygulama:
constnow=2026;constageAli= now -1990;constageVeli= now -2010;console.log(ageAli > ageVeli);// true (Doğru) döndürür.
Metinleri birleştirmek için eski yöntemde artı (+) işareti kullanılırdı. Modern JavaScript'te backtick (`) işaretleri kullanılarak yazılan Template Literals ile değişkenler metnin içine doğrudan gömülür.
Uygulama:
constname="Can";constjob="Öğretmen";// Eski yöntem:conststringEski="Ben "+ name +", bir "+ job +"im.";// Modern yöntem (Template Literal):conststringYeni=`Ben ${name}, bir ${job}im.`;
Kodun belirli şartlara göre
farklı yollardan gitmesini sağlar. Şart doğruysa if
bloğu, yanlışsa else
bloğu çalışır.
Uygulama: Ehliyet alma kontrolü:
constage=16;if(age >=18) {console.log("Ehliyet alabilirsin! 🚗");}else{constyearsLeft=18- age;console.log(`Ehliyet almak için ${yearsLeft} yıl beklemen gerek.`);}
Conversion (Dönüşüm): Bizim isteyerek bir tipi diğerine çevirmemizdir.
Coercion (Zorlama): JavaScript'in arka planda tipleri otomatik olarak birbirine uydurmasıdır.
Uygulama:
// DönüşümconstinputYear="1998";console.log(Number(inputYear) +10);// 2008// Zorlamaconsole.log("Ben "+23+" yaşındayım");// Sayı olan 23'ü otomatik yazıya çevirir.console.log("23"-"10"-3);// Eksi işareti yazıları otomatik sayıya çevirir -> Sonuç: 10
JavaScript'te tam olarak Boolean
(true/false) olmayan ama mantıksal bir sorguya sokulduğunda false
gibi davranan 5 değer vardır: 0,
""
(boş yazı), undefined,
null,
NaN.
Bunlar dışındaki her şey true
kabul edilir.
Uygulama:
letmoney=0;// 0 falsy bir değerdir.if(money) {console.log("Paran var.");}else{console.log("Paran yok ya da 0 lira!");// Burası çalışır.}
===
(Katı Eşitlik): Hem değerlerin hem de veri tiplerinin aynı
olmasını ister. Güvenlidir.
==
(Gevşek Eşitlik): Tipleri önemsemez, sadece değerleri uydurmaya
çalışır. Güvensizdir.
Uygulama:
console.log(18==="18");// false (Biri sayı, biri yazı)console.log(18=="18");// true (Yazıyı sayıya uydurur)
Birden fazla şartı birleştirmek
için kullanılır. AND (ve -> &&),
OR (veya -> ||),
NOT (değil -> !).
Uygulama:
consthasDriversLicense=true;consthasGoodVision=false;console.log(hasDriversLicense && hasGoodVision);// false (İkisi de doğru olmalıydı)console.log(hasDriversLicense || hasGoodVision);// true (En az biri doğru olsa yeter)
Bir değişkenin çok sayıda
farklı değere eşit olma durumunu karmaşık if-else
yapıları yerine daha temiz bir şekilde kontrol etmeyi sağlar.
Uygulama:
constday="pazartesi";switch(day) {case"pazartesi":console.log("Kursa çalış");break;case"salı":console.log("Kodlama yap");break;default:console.log("Dinlen");}
Expression (İfade): Bir
değer üreten her kod parçasıdır (Örn: 3
+ 4 veya true).
Statement (Deyim): Bir eylem gerçekleştiren büyük
kod cümleleridir (Örn: Tüm bir if-else
yapısı).
Tek satırda hızlıca if-else
yazmamızı sağlayan üçlü operatördür. şart
? doğruysa_burası : yanlışsa_burası
şeklinde çalışır.
Uygulama:
constage=20;constdrink= age >=18?"Kahve ☕":"Süt 🥛";console.log(drink);// Kahve
JavaScript sürekli gelişen bir dildir. 2015 yılında çıkan ES6 (ECMAScript 6) sürümü dile çağ atlatmıştır. Tarayıcıların eski kodları anlaması için Babel gibi araçlar kullanılır.
Bu bölümde kodlarımızı paketlemeyi, veri listeleri oluşturmayı ve döngülerle çalışmayı öğreniriz.
Kodun en başına yazılan bir metindir. JavaScript'in bazı hataları sessizce geçiştirmesini engeller, konsolda görünür hata verir ve bizi daha güvenli kod yazmaya zorlar.
Uygulama:
"use strict";lethasDriversLicense=false;constpassTest=true;if(passTest) hasDriverLicense =true;// Yazım hatası yapıldı (s eksik)// Strict mode açık olduğu için konsolda "hasDriverLicense is not defined" hatası verir.
Fonksiyonlar, tekrar tekrar kullanabileceğimiz kod bloklarıdır. İçine veri alabilir (parametre) ve dışarıya bir sonuç fırlatabilir (return).
Uygulama:
functionmeyveSıkacağı(elmalar,portakallar) {constmeyveSuyu=`${elmalar} elma ve ${portakallar} portakal içeren meyve suyu.`;returnmeyveSuyu;}consttazeIçecek= meyveSıkacağı(2,3);console.log(tazeIçecek);
Fonksiyon yazmanın üç yolu vardır:
Declaration: Klasik yöntemdir, kodda tanımlanmadan önce bile çağrılabilir.
Expression: Fonksiyon bir değişkene eşitlenir. Tanımlanmadan önce çağrılamaz.
Arrow Function: Modern, tek
satırlık ve kısa fonksiyonlar yazmak için ok (=>)
işareti kullanılır.
Uygulama:
// DeclarationfunctioncalcAge1(birthYear) {return2026- birthYear; }// ExpressionconstcalcAge2=function(birthYear) {return2026- birthYear; };// ArrowconstcalcAge3= birthYear =>2026- birthYear;
Diziler, tek bir değişken içinde birden fazla veriyi sıra halinde saklamamızı sağlayan listelerdir. İçerisinde eleman ekleme, çıkarma gibi metotlar barındırır.
Uygulama:
constfriends= ["Ali","Veli","Ayşe"];friends.push("Fatma");// Sona eleman ekler -> ["Ali", "Veli", "Ayşe", "Fatma"]friends.pop();// Sondan eleman çıkarır -> ["Ali", "Veli", "Ayşe"]friends.unshift("Can");// Başa eleman ekler -> ["Can", "Ali", "Veli", "Ayşe"]
Dizilerde elemanların sırası
önemlidir. Nesnelerde ise sıranın önemi yoktur, veriler
"Anahtar-Değer" (Key-Value) çiftleri olarak saklanır.
Verilere Nokta (.)
veya Parantez ([])
yöntemiyle erişilir.
Uygulama:
constahmet= {firstName:"Ahmet",lastName:"Yılmaz",birthYear:1990,job:"Geliştirici",// Nesne içine fonksiyon (Metot) da eklenebilir:calcAge:function() {return2026-this.birthYear;// 'this' nesnenin kendisini ifade eder.}};console.log(ahmet.firstName);// Nokta notasyonu -> Ahmetconsole.log(ahmet["lastName"]);// Parantez notasyonu -> Yılmazconsole.log(ahmet.calcAge());// 36
Belirli bir kod bloğunu, bir şart sağlandığı sürece tekrar tekrar çalıştırmak için döngüler kullanılır.
for:
Tekrar sayısı genellikle önceden bellidir.
while:
Sadece bir şarta bağlıdır, şart doğru olduğu sürece döner.
break:
Döngüyü tamamen durdurur.
continue:
Döngünün o anki adımını pas geçip bir sonraki adıma atlar.
Uygulama:
// For Döngüsüfor(leti=1; i <=3; i++) {console.log(`${i}. tekrar`);}// While Döngüsületdice=1;while(dice !==6) {dice = Math.trunc(Math.random() *6) +1;// 1-6 arası rastgele sayıconsole.log(`Zar atıldı: ${dice}`);}
Kod yazarken hızlanmak ve profesyonel araçları kullanmak bu bölümün temel amacıdır.
Kodlarımızı yazmak için VS Code editörünü kullanırız. Kodların otomatik olarak süslenmesi, girintilerin ve boşlukların standart hale gelmesi için Prettier eklentisi kurulur.
Tarayıcı dışındaki bilgisayar sisteminde JavaScript çalıştırmak ve terminal araçlarını yönetmek için bilgisayara Node.js kurulur.
Yazılan koddaki mantık hatalarını
veya çökmeleri bulma sürecidir. console.log()
kullanılarak değişkenlerin anlık değerlerine bakılır. Daha
profesyonelce yapmak için tarayıcının inceleme kısmındaki
Breakpoints (Durdurma
noktaları) kullanılır; kod satır satır durdurularak incelenir.
ChatGPT, GitHub Copilot veya Cursor AI gibi modern yapay zeka araçları kodlama sürecini hızlandırır. Bu araçlara doğru sorular (prompt) sorularak hata çözümleri veya algoritma tasarımları istenir.
Tarayıcıda JavaScript ile görsel işlemler yapabilmek için web sayfalarının iskeletini ve kıyafetini bilmek gerekir.
HTML Yapısı: Web
sayfasındaki başlıklar (<h1>),
paragraflar (<p>),
butonlar (<button>)
ve kutular (<div>)
gibi elementleri oluşturur. Class ve ID özellikleri ile bu
elementlere kimlik verilir.
CSS Kutu Modeli (Box Model): Her HTML elementini bir kutu olarak görür. Bu kutunun içeriği (content), iç boşluğu (padding), çerçevesi (border) ve dış boşluğu (margin) vardır. Bu model web sayfalarının düzenini belirler.
Bu bölüm, JavaScript kullanarak web sayfalarını canlandırdığımız ilk proje bölümüdür. Kurs bu kısımda 3 büyük proje yaptırır: "Numaramı Tahmin Et!", "Açılır Pencere (Modal)" ve "Domuz Oyunu (Pig Game)".
DOM, HTML sayfasının tarayıcı tarafından oluşturulan bir ağaç haritasıdır. JavaScript bu haritayı kullanarak HTML elementlerini seçebilir, silebilir, değiştirebilir veya yeni element ekleyebilir. DOM tarayıcının bize sunduğu bir özelliktir, saf JavaScript'in bir parçası değildir.
Uygulama: Sayfadaki bir yazıyı değiştirmek:
// HTML'de <p class="message">Eski Yazı</p> olduğunu varsayalım:constmessageElement= document.querySelector(".message");messageElement.textContent ="Yeni Başarı Mesajı! 🎉";
Kullanıcının sayfada yaptığı
tıklama, klavyeye basma gibi hareketlere "Event" (Olay)
denir. addEventListener
ile bu olaylar dinlenir ve gerçekleştiğinde bir fonksiyon
tetiklenir.
Uygulama: Butona tıklandığında arka planı değiştirme:
constbtn= document.querySelector(".btn-click");btn.addEventListener("click",function() {document.querySelector("body").style.backgroundColor ="green";});
DRY (Don't Repeat Yourself - Kendini Tekrar Etme) yazılımın en önemli kuralıdır. Eğer aynı kod bloklarını birden fazla yerde yazdıysanız, o kodları tek bir fonksiyon içine alıp temizleme işlemine Refactoring denir.
Bu bölüm tamamen teoriktir ve bilgisayar hafızasında nelerin döndüğünü anlatır.
JavaScript kodlarını bilgisayarın anlayacağı makine koduna çeviren programlara motor denir (Örn: Chrome içindeki V8 motoru). Tarayıcı ise bu motora ek olarak DOM API'lerini ve Event Loop yapısını içeren bir çalışma ortamı (Runtime) sunar.
Kod çalışmaya başladığında küresel bir alan (Global Execution Context) oluşur. Her fonksiyon çağrıldığında o fonksiyona ait yeni bir kutu oluşturulur ve Call Stack (Çağrı Yığını) adlı üst üste dizilen bir kuleye konur. İş biten fonksiyon kuleden atılır.
Değişkenlere kodun hangi bölgesinden erişebileceğimizi belirler.
Global Scope: Her yerden erişilen alan.
Function Scope: Sadece o fonksiyon içinden erişilen alan.
Block Scope (ES6): let
ve const
ile oluşturulan değişkenler sadece bulundukları süslü parantez
{}
içinden erişilebilir. if
veya for
içindeki değişkenler dışarıya sızamaz.
JavaScript, kodları çalıştırmadan önce tarar ve değişken tanımlamalarını hafızada en yukarıya taşır gibi davranır. Buna Hoisting denir.
var
ile tanımlananlar yukarı taşınır ama değerleri undefined
olur.
let
ve const
ile tanımlananlar yukarı taşınır fakat kod satırı gelene
kadar erişilemez kilitli bir bölgede kalırlar. Bu güvenli
kilitli döneme TDZ (Temporal Dead Zone) denir.
this,
o fonksiyonu o an kimin veya hangi nesnenin çalıştırdığını
gösteren dinamik bir kelimedir.
Normal fonksiyonlarda this,
fonksiyonu çağıran nesneyi gösterir.
Ok fonksiyonlarında (Arrow Functions) kendilerine ait bir
this
yoktur, bulundukları dış çevrenin (Lexical Scope) this
özelliğini miras alırlar.
Primitive (İlkel) Tipler (Sayı, Yazı, Boolean): Değerleri doğrudan Stack adı verilen hızlı hafızada saklanır. Bir değişkeni diğerine eşitlediğinizde değer kopyalanır.
Reference (Referans) Tipler (Nesneler, Diziler): Büyük veriler oldukları için Heap adı verilen geniş hafızada tutulurlar. Değişkende ise sadece o verinin adresi (referansı) yazar.
Uygulama: Referans kopyalama tehlikesi:
constkisi1= {isim:"Can"};constkisi2= kisi1;// Adres kopyalandı!kisi2.isim ="Efe";console.log(kisi1.isim);// "Efe" olur! Çünkü ikisi de aynı Heap adresine bakıyor.
Bunu önlemek için nesnenin yüzeysel kopyasını (Shallow Copy)
oluşturan Object.assign({},
kisi1) veya derin kopyasını (Deep Copy)
oluşturan yapılar kullanılır.
Bu bölüm, verileri çok daha hızlı işlememizi sağlayan modern araçları kapsar.
Büyük bir dizi veya nesne içindeki verileri tek hamlede çıkarıp ayrı ayrı değişkenlere atama yöntemidir.
Uygulama:
// Dizi Parçalamaconstarr=;const[x,y,z] = arr;// x=2, y=3, z=4 olur.// Nesne Parçalamaconstrestoran= {ad:"Lezzet",puan:5};const{ad,puan} = restoran;// ad="Lezzet", puan=5 adında iki değişken oluşur.
Üç nokta (...)
işareti kullanıldığı yere göre iki farklı işe yarar:
Spread (Yayma): Bir dizideki tüm elemanları kutusundan çıkarıp tek tek saçar. Yeni dizi oluştururken çok kullanışlıdır.
Rest (Toplama): Fonksiyona gelen çok sayıda parametreyi tek bir dizi altında toplar.
Uygulama:
// Spread ÖrneğiconsteskiDizi=;constyeniDizi= [...eskiDizi,3,4];// [1, 2, 3, 4] olur.// Rest Örneğifunctiontopla(...sayilar) {// Gelen tüm sayıları bir dizi yaparreturnsayilar.reduce((a,b) => a + b,0);}console.log(topla(2,5,8));// 15
||
(Veya): İlk bulduğu doğru (truthy) değeri döndürür.
Varsayılan değer atamak için kullanılır.
&&
(Ve): İlk bulduğu yanlış (falsy) değeri döndürür. Şart
doğruysa bir sonraki kodu çalıştırmak için kullanılır.
??
(Nullish): Sadece değer null
veya undefined
ise sağdaki değeri seçer. 0
veya boş yazıyı ("")
geçerli kabul eder.
Uygulama:
letmisafirSayisi=0;constkonuklar1= misafirSayisi ||10;// 0 falsy olduğu için 10 seçilir.constkonuklar2= misafirSayisi ??10;// 0 geçerli kabul edilir, sonuç 0 olur.
Set: İçinde asla tekrar eden (dublike) eleman barındırmayan özel bir koleksiyondur.
Map: Nesnelere benzer ama nesnelerden farklı olarak anahtar (key) kısmına sadece yazı değil; sayı, dizi hatta fonksiyon bile koyulabilir.
Uygulama:
// Set Örneğiconstsiparisler=newSet(["Döner","Pizza","Döner"]);console.log(siparisler);// Set(2) {"Döner", "Pizza"} -> Tekrar eden silindi.// Map Örneğiconstsoru=newMap();soru.set("soruMetni","JS güzel mi?");soru.set(true,"Harika! Doğru cevap.");// Anahtar bir Boolean!
Metinler üzerinde arama yapma, parçalama ve değiştirme fonksiyonlarıdır.
indexOf(),
lastIndexOf():
Karakterin konumunu bulur.
slice():
Metnin belirli bir kısmını kesip alır.
split():
Metni belirtilen karaktere göre bölüp diziye çevirir.
join():
Dizideki elemanları birleştirip metin yapar.
Uygulama: Bir ismi temizleme:
constyolcuIsmi=" aHMeT ";consttemizIsim= yolcuIsmi.trim().toLowerCase();// "ahmet"constilkHarfBuyuk= temizIsim[0].toUpperCase() + temizIsim.slice(1);// "Ahmet"
Fonksiyonların gelişmiş özellikleri ve en zor konulardan biri olan Closures (Kapanışlar) burada yer alır.
JavaScript'te fonksiyonlar birer "değer" gibi görülür. Değişkenlere atanabilir, başka fonksiyonlara parametre olarak gönderilebilir veya bir fonksiyonun içinden dışarıya fonksiyon fırlatılabilir. Başka bir fonksiyonu içine alan ya da dışarıya fonksiyon döndüren yapılara Higher-Order Function denir.
Uygulama: Callback (Geri çağrım) kullanımı:
consttekBosluk= str => str.replace(/ /g,"");// Yüksek dereceli fonksiyon: İçine başka fonksiyon alıyorconstdonusturici=function(str,fn) {console.log(`Orijinal metin: ${str}`);console.log(`Dönüşmüş metin: ${fn(str)}`);};donusturici("Selam Dunya Yazilim", tekBosluk);
Bir fonksiyonun içindeki this
kelimesinin hangi nesneyi göstereceğini dışarıdan zorla
belirlemek için kullanılırlar.
call():
Fonksiyonu hemen çalıştırır, parametreleri tek tek alır.
apply():
Fonksiyonu hemen çalıştırır, parametreleri dizi olarak alır.
bind():
Fonksiyonu hemen çalıştırmaz, this
kelimesi kilitlenmiş yeni bir fonksiyon kopyası üretir.
Tanımlandığı an otomatik olarak hemen çalışan ve bir daha asla çağrılamayan fonksiyonlardır. Geçmişte sadece değişkenleri dış dünyadan gizlemek (kapsüllemek) için kullanılırdı.
Uygulama:
(function() {console.log("Bu kod anında çalışır ve kaybolur!");constgizliVeri=42;})();
Bir fonksiyon, doğduğu ortamdaki (kapsamdaki) değişkenleri, o ortam yok olduktan sonra bile hatırlıyorsa buna Closure denir. Fonksiyon, yaratıldığı yerin değişken ortamına sıkı sıkıya bağlı bir görünmez çanta ile gezer.
Uygulama:
constyolcuSayimi=function() {letyolcuSayisi=0;// Bu fonksiyonun içindeki yerel değişkenreturnfunction() {yolcuSayisi++;console.log(`${yolcuSayisi} yolcu var.`);};};constbiletKes= yolcuSayimi();biletKes();// 1 yolcu var.biletKes();// 2 yolcu var. (yolcuSayimi fonksiyonu bitmesine rağmen değeri unutmadı!)
Bu bölüm, modern JavaScript projelerinde en çok kullanılan veri dönüştürme metotlarını (map, filter, reduce) "Bankist" adlı görsel bir banka uygulaması üzerinden öğretir.
forEach():
Dizideki her eleman için bir fonksiyon çalıştırır (Döngünün
modern hali).
at():
Negatif sayılar vererek dizinin sondaki elemanlarına kolayca
erişmeyi sağlar (arr.at(-1)
sondaki elemanı verir).
flat(),
flatMap():
İç içe geçmiş dizileri tek bir düz dizi haline getirir.
map():
Orijinal dizideki her elemanı bir işlemden geçirip aynı
uzunlukta yeni bir dizi üretir.
filter():
Belirtilen şarta uyan elemanları ayıklayıp daha kısa yeni
bir dizi üretir.
reduce():
Dizideki tüm elemanları birbiriyle işleme sokarak tek bir
nihai değer (Örn: Toplam değer) üretir.
Uygulama: Hesap hareketleri analizi:
constislemler= [200,450, -400,3000, -650, -130];// 1. Doları Euro'ya Çevirme (Map)consteurToUsd=1.1;constdolarKarşılıgı= islemler.map(mov => mov * eurToUsd);// 2. Sadece Yatırılan Paraları Bulma (Filter)constyatirilanlar= islemler.filter(mov => mov >0);// [200, 450, 3000]// 3. Toplam Bakiyeyi Hesaplama (Reduce)constbakiye= islemler.reduce((acc,mov) => acc + mov,0);// acc biriktiricidir.
find():
Şartı sağlayan ilk elemanın kendisini döner.
findIndex():
Şartı sağlayan ilk elemanın sıra numarasını (index)
döner.
some():
Dizide en az bir eleman şarta uyuyor mu diye bakar (true/false).
every():
Dizideki tüm elemanlar şarta uyuyor mu diye bakar.
sort():
Diziyi alfabetik ya da sayısal olarak sıralar. Orijinal diziyi
kalıcı olarak değiştirir. Değiştirmeyen modern alternatifleri
ise toSorted(),
toReversed()
metotlarıdır.
Web uygulamalarında finansal hesaplar, zaman sayaçları ve dünya standartlarında tarih gösterimleri bu bölümün konusudur.
JavaScript'te tüm sayılar arkada
64-bitlik kayan noktalı (floating point) sistemle saklanır. Bu
yüzden 0.1
+ 0.2
tam olarak 0.3
çıkmaz, 0.30000000000000004
çıkar. Çok büyük tam sayılarla hassas hesap yapmak için
sayının sonuna n
konularak BigInt veri
tipi kullanılır.
Zamanı milisaniye cinsinden yönetmek ve tarih objeleri oluşturmak için kullanılır.
Uygulama:
constsu An =newDate();console.log(suAn.getFullYear());// Bulunduğumuz yılı verir.// İki tarih arasındaki gün farkını bulma:constgunFarki= (tarih1,tarih2) => Math.abs(tarih2 - tarih1) / (1000*60*60*24);
Web sitenizdeki sayıları veya tarihleri kullanıcının yaşadığı ülkenin dil ve para birimi formatına otomatik çevirir.
Uygulama: Finansal gösterim:
constpara=3500450.5;constsecenekler= {style:"currency",currency:"TRY"};constturkceFormat=newIntl.NumberFormat("tr-TR", secenekler).format(para);console.log(turkceFormat);// "₺3.500.450,50" şeklinde tertemiz yazdırır.
setTimeout():
Belirtilen süre bittiğinde fonksiyonu bir kez çalıştırır.
setInterval():
Durdurulana kadar her belirtilen süre aralığında fonksiyonu
sürekli çalıştırır (Örn: Geri sayım sayaçları).
Bu bölümde web sitelerine profesyonel efektler eklemeyi ("Bankist" web sitesi projesi üzerinden) öğreniriz.
Bir HTML elementine (Örn: bir liste elemanına) tıklandığında, o tıklama olayı sanki suyun altındaki bir hava kabarcığı gibi yukarıdaki tüm ana elementlere (parent) doğru yayılır. Buna Bubbling denir.
Event Delegation (Olay Delege Etme): Sayfada 100 tane butona ayrı ayrı tıklama olayı eklemek yerine, hepsinin bağlı olduğu tek bir üst kutuya (parent) olay eklenir ve tıklanan elemanın kimliği tespit edilir. Bu, sitenin performansını uçurur.
Kullanıcının sayfayı aşağı kaydırırken belirli bir resme veya bölüme gelip gelmediğini ekran sınırlarına göre tespit eden çok güçlü bir tarayıcı özelliğidir.
Kullanım Alanı: Sayfa aşağı kaydırıldığında yukarıdan yapışkan menü (Sticky Navigation) çıkması veya aşağıda kalan büyük resimlerin performans için ekrana yaklaştıkça yüklenmesi (Lazy Loading Images).
Büyük projeleri sınıflar (Classes) yardımıyla organize etme felsefesidir.
JavaScript'teki OOP mimarisi diğer dillerden (Java, C#) farklıdır. JavaScript'te sınıflar aslında arka planda Prototip (Prototype) adı verilen objelere dayanır. Oluşturduğunuz her nesne, bağlı olduğu sınıfın prototipindeki fonksiyonları ortaklaşa kullanır. Bu sayede bilgisayar hafızasından devasa tasarruf sağlanır.
ES6 ile gelen class
kelimesi aslında prototip sisteminin üzerine giydirilmiş süslü
bir kıyafettir (Syntactic Sugar). Yazımı çok daha kolay ve
temizdir.
Uygulama: Bir Araba sınıfı tasarlamak:
classAraba{constructor(marka,hiz) {this.marka = marka;this.hiz = hiz;}// Prototip metodu:hizlan() {this.hiz +=10;console.log(`${this.marka} şimdi ${this.hiz} km/h hızda.`);}}constozelAraba=newAraba("Tesla",120);ozelAraba.hizlan();
Dışarıdaki kodların, sınıfın
içindeki hassas verilere doğrudan erişip bozmasını engellemek
için bazı değişkenler gizlenir. Modern JavaScript'te değişken
isminin başına kare (#)
işareti konularak o alan Private (Gizli)
yapılır.
Bu bölümde tamamen nesne yönelimli mimari (OOP) kullanılarak "Mapty" adında bir spor/harita uygulaması geliştirilir.
Geolocation API: Tarayıcıdan izin isteyerek kullanıcının o anki dünya üzerindeki enlem ve boylam koordinatlarını alır.
Leaflet Library: Açık kaynaklı harika bir harita kütüphanesidir. JavaScript kodumuza dahil edilerek sayfada etkileşimli bir harita kutusu açılmasını ve tıklanan yerlere özel spor ikonları (marker) yerleştirilmesini sağlar.
localStorage: Kullanıcı sayfayı kapatsa veya yenilese bile eklediği spor aktivitelerinin bilgisayarın tarayıcı hafızasında kalıcı olarak saklanmasını sağlar.
JavaScript normalde tek hat üzerinden sırayla çalışan (Single-threaded, synchronous) bir dildir. Bir işlem uzun sürerse (Örn: internetten büyük veri çekmek) tüm sayfa donar. Bunu önlemek için asenkron yapı kullanılır.
AJAX: Sayfayı tamamen yenilemeden arka planda sunucudan veri alışverişi yapma tekniğidir.
API: Bir sunucunun dış dünyaya sunduğu, veri çekebileceğimiz kapılardır (Örn: Hava durumu verileri sunan bir API).
Eski yöntemde asenkron işlemleri peş peşe yapmak için fonksiyon içine fonksiyon yazılırdı. Bu durum kodun sağa doğru okunamaz hale gelmesine (Callback Hell - Callback Cehennemi) neden olurdu. Bu sorunu çözmek için Promise (Söz) yapısı getirilmiştir. Promise, gelecekte tamamlanacak bir işlemin sonucunu temsil eder.
Promise yapılarını tıpkı düz,
senkron kod yazıyormuş gibi alt alta tertemiz yazmamızı sağlayan
en modern ve ödüllü JavaScript özelliğidir. Hataları yakalamak
için klasik try...catch
blokları kullanılır.
Uygulama: İnternetten ülke verisi çekme:
constulkeVerisiGetir=asyncfunction(ulkeAdi) {try{// Veri gelene kadar satırda bekle (await)constresponse=awaitfetch(`https://restcountries.com{ulkeAdi}`);if(!response.ok)thrownewError("Ülke bulunamadı!");constveri=awaitresponse.json();console.log(veri[0]);// Ülkenin tüm bilgileri ekranda}catch(hata) {console.error(`Üzgünüz bir hata oldu: ${hata.message}`);}};ulkeVerisiGetir("turkey");
Eğer birbirini beklemesi
gerekmeyen 3 farklı internet sitesinden aynı anda veri çekeceksek,
bunları alt alta yazıp birbirini bekletmek yerine Promise.all
ile hepsini aynı anda (paralel) başlatıp hız kazanırız.
Büyük projelerde tüm kodları
tek bir .js
dosyasına yazmak imkansızdır. Kodları parçalara bölüp yönetmek
gerekir.
ES6 Modülleri: Kodları
mantıksal dosyalar halinde ayırmamızı sağlar. Bir dosyadaki
fonksiyonu dışa aktarıp (export),
başka bir dosyada içe aktararak (import)
kullanırız.
NPM (Node Package Manager): Dünyadaki diğer yazılımcıların yazdığı hazır paketleri ve kütüphaneleri projemize tek tıkla kurmamızı sağlayan paket yönetim sistemidir.
Parcel (Bundler / Paketleyici): Yazdığımız onlarca farklı JavaScript, CSS ve resim dosyasını tarayıcıların çok hızlı okuyabileceği tek bir sıkıştırılmış dosya haline getiren modern bir araçtır.
Babel: Yazdığımız en modern ES6+ kodlarını, eski model tarayıcıların (Örn: Internet Explorer) bile anlayabileceği eski ES5 formatına otomatik çeviren bir dönüştürücüdür (Polyfilling).
Kursun en büyük, zirve projesidir. İçinde yemek tarifleri arama, malzeme listelerini porsiyona göre güncelleme, tarif defterine kaydetme ve API'ye yeni tarif yükleme özellikleri olan modern bir yemek platformu inşa edilir.
MVC Mimarisi (Model-View-Controller): Büyük projelerin çorba olmasını engellemek için kodlar 3 ana parçaya bölünür:
Model: Verileri ve internetten veri çekme işlerini yönetir.
View: Ekrandaki görselliği, HTML basma ve buton tıklamalarını yönetir.
Controller: Model ile View arasında bir köprüdür. Ekranda butona basıldığında arka plandaki veriyi tetikler, gelen sonucu tekrar ekrana gönderir.
Publisher-Subscriber Kalıbı: View katmanının (görsel alanın), Controller katmanındaki fonksiyonlardan haberdar olmasını sağlayan çok profesyonel bir tasarım kalıbıdır.
Yazılan projenin dünyaya sunulma aşamasıdır.
Git & GitHub: Kodlarımızın geçmiş versiyonlarını kaydetmemizi, hata yaparsak geri dönebilmemizi ve kodları internet üzerinde güvenle saklamamızı sağlayan versiyon kontrol sistemidir.
Netlify & Sürekli Entegrasyon (CI): Hazırladığımız web projesini internete ücretsiz yükleyerek herkesin erişebileceği bir link alma sürecidir. GitHub hesabımıza bağlandığında, bilgisayarımızda kodu güncelleyip GitHub'a attığımız an web sitesi internette otomatik olarak saniyeler içinde güncellenir.
************************************
Modern JavaScript From The Beginning 2.0 kurs müfredatı belgesini satır satır ele alarak, istediğiniz kurallar doğrultusunda tüm konuları derinlemesine inceliyoruz.
Bu paragraf, kursu tamamladığınızda kazanacağınız temel ve ileri düzey yazılım yeteneklerini özetler. Kurs, tarayıcıların dinamik olarak çalışmasını sağlayan temel mantıktan başlar. Ardından kodun arka planda nasıl yürütüldüğünü (hafıza yönetimi, asenkron motorlar) ve web sayfalarındaki elemanlara nasıl hükmedebileceğinizi (DOM ve Etkinlikler) öğretir. Sadece kod yazmayı değil; modern endüstri standartlarında kullanılan araçları (Webpack, Babel, NPM), Nesne Yönelimli Programlama (OOP) mimarilerini ve veritabanı bağlantılı (Node, Express, MongoDB) tam donanımlı Full Stack uygulamalar geliştirmeyi vadeder. Gerçek dünya projeleriyle bu teorik bilgileri kalıcı pratiğe dönüştürmeyi amaçlar.
Müfredat satırlarından ayrıştırılan ana konu başlıkları aşağıda listelenmiştir. Her konu teorik altyapısı, kod örneği ve tarayıcıda/Node ortamında doğrudan çalıştırabileceğiniz pratik bir uygulama senaryosu ile ele alınmıştır.
JavaScript, web sayfalarına
dinamizm ve etkileşim kazandıran, tarayıcılarda doğrudan
yorumlanan güçlü bir programlama dilidir. Kodlarımızı test
etmek, hataları ayıklamak ve tarayıcıyla iletişim kurmak için
geliştirici araçlarında bulunan console
(konsol) yapısını kullanırız.
Örnek:
Konsola yazı yazdırmak veya matematiksel hesaplamaları anlık
görmek için console.log()
kullanılır.
Uygulama: Tarayıcınızın inceleme (F12) ekranını açıp konsola aşağıdaki kodu yazın:
console.log("Sistem başarıyla başlatıldı.");console.warn("Bu bir uyarı mesajıdır.");console.error("Kritik bir hata oluştu!");
JavaScript'te verileri hafızada
tutmak için değişkenler (let,
var)
ve değiştirilemeyen sabitler (const)
kullanılır. Veri tipleri ikiye ayrılır: İlkel (Primitive) tipler
(String, Number, Boolean, Null, Undefined, Symbol) değerleri
doğrudan hafızada tutar. Referans (Reference) tipleri (Nesneler,
Diziler) ise hafızadaki bir adresi (referansı) işaret eder.
Örnek: İlkel bir veri kopyalandığında bağımsız bir kopyası oluşur. Referans veri kopyalandığında ise aynı kutuyu işaret ederler; birinde yapılan değişiklik diğerini de etkiler.
Uygulama:
// İlkel Tip Denemesiletisim1="Ahmet";letisim2= isim1;// Değer kopyalandıisim1 ="Mehmet";console.log(isim2);// Çıktı: "Ahmet" (Etkilenmedi)// Referans Tip Denemesiletdizi1= [1,2,3];letdizi2= dizi1;// Adres kopyalandıdizi1.push(4);console.log(dizi2);// Çıktı: [1, 2, 3, 4] (Etkilendi!)
Tip dönüşümü, yazılımcının
bir veriyi bilerek başka bir tipe çevirmesidir (Number(),
String()).
Tip dayatması ise JavaScript motorunun işlem sırasında veri
tiplerini kendi kendine otomatik olarak dönüştürmesidir.
Örnek: Bir metin ile sayıyı toplamaya çalışırsanız JavaScript sayıyı metne dönüştürür.
Uygulama:
// Manuel Dönüşüm (Conversion)letmetinSayi="42";letgercekSayi= Number(metinSayi);console.log(gercekSayi +8);// Çıktı: 50// Otomatik Dayatma (Coercion)letsonuc="5"+5;console.log(sonuc);// Çıktı: "55" (Metin birleştirme yaptı)letfark="10"-2;console.log(fark);// Çıktı: 8 (Çıkarma işleminde sayıya zorladı)
Matematiksel karmaşık
hesaplamalar için yerleşik Math
nesnesi kullanılır. Zaman, saat ve gün yönetimleri ise Date
nesnesi ve modern Intl.DateTimeFormat
API'leri yardımıyla yerelleştirilerek çözülür.
Örnek: Sayıları yuvarlama, rastgele sayı üretme veya bugünün tarihini yerel dilde yazdırma işlemleri.
Uygulama:
// Rastgele sayı üretme (1 ile 10 arasında)letrastgele= Math.floor(Math.random() *10) +1;console.log("Rastgele Sayı: "+ rastgele);// Tarihi Türkçe formatta yazdırmaletbugun=newDate();letformatliTarih=newIntl.DateTimeFormat('tr-TR', {dateStyle:'full'}).format(bugun);console.log("Bugün: "+ formatliTarih);
Diziler, sıralı veri listelerini
tutar. Nesneler ise anahtar-değer (key-value) çiftleriyle
yapılandırılmış karmaşık veri modelleri oluşturmamızı
sağlar. ES6 ile gelen Spread (...)
operatörü bu yapıları kopyalamayı ve birleştirmeyi
kolaylaştırır. Destructuring ise içlerindeki verileri tek hamlede
dışarı çıkarmayı sağlar.
Örnek: Kullanıcı listeleri dizilerde, tek bir kullanıcının detay profili ise nesnelerde tutulur.
Uygulama:
// Nesne ve Destructuring Uygulamasıconstkullanici= {ad:"Can",yas:28,roller: ["Admin","Yazar"]};const{ad,yas} = kullanici;// Destructuringconsole.log(`${ad} kişisi ${yas} yaşında.`);// Spread Operatörü ile Dizi BirleştirmeconstSayilar1= [1,2];constSayilar2= [3,4];constbirlesikDizi= [...Sayilar1, ...Sayilar2];console.log(birlesikDizi);// Çıktı: [1, 2, 3, 4]
Fonksiyonlar yeniden kullanılabilir kod bloklarıdır. Kod çalıştırılırken JavaScript motoru bir "Execution Context" (Çalışma Bağlamı) oluşturur. Önce hafıza yerleri ayrılır, sonra kod satır satır işletilir. Kapsam (Scope) ise değişkenlerin nerelerden erişilebilir olduğunu belirler (Global, Function, Block). [1, 2, 3]
Örnek:
let
ve const
blok kapsamlıdır ({}
dışından erişilemez), fonksiyonlar ise kendi içlerinde izole
alanlar yaratır.
Uygulama:
constglobalDegisken="Ben her yerdeyim";functionscopeTest() {letfonksiyonIci="Sadece bu fonksiyonda";if(true) {letblokIci="Sadece bu if bloğunda";vareskiYontem="Blok dinlemez, fonksiyona sızar";}// console.log(blokIci); // HATA VERİR!console.log(eskiYontem);// Çalışır}scopeTest();
Programın kararlar almasını
sağlayan yapılar (if-else,
switch,
ternary)
ve işlemlerin tekrar etmesini sağlayan döngüler (for,
while,
for...of,
for...in)
bu başlık altındadır. Ayrıca truthy
(doğru kabul edilen) ve falsy
(yanlış kabul edilen: 0,
"",
null,
undefined)
kavramları akış yönetiminde kritik öneme sahiptir.
Örnek: Kullanıcı giriş yapmışsa paneli göster, yapmamışsa uyarı ver döngüsü.
Uygulama: (Klasik FizzBuzz mülakat sorusu uygulaması)
// 1'den 15'e kadar dön, 3'ün katlarına Fizz, 5'in katlarına Buzz, ikisinin katına FizzBuzz yaz.for(leti=1; i <=15; i++) {if(i %3===0&& i %5===0) {console.log("FizzBuzz");}elseif(i %3===0) {console.log("Fizz");}elseif(i %5===0) {console.log("Buzz");}else{console.log(i);}}
Diziler üzerinde döngü kurmak
yerine modern JavaScript'te fonksiyonel metotlar tercih edilir.
forEach
listeyi gezer, filter
şartı sağlayanları süzer, map
elemanları dönüştürerek yeni dizi üretir, reduce
tüm diziyi tek bir değere indirger.
Örnek:
Fiyat listesindeki ürünlere zam yapmak (map)
veya pahalı olanları seçmek (filter).
Uygulama:
consturunler= [{ad:"Kitap",fiyat:50},{ad:"Kalem",fiyat:20},{ad:"Defter",fiyat:80}];// Fiyatı 30'dan büyük olanları filtreleconstpahaliUrunler= urunler.filter(urun => urun.fiyat >30);console.log(pahaliUrunler);// Tüm ürünlerin toplam fiyatını hesaplaconsttoplamFiyat= urunler.reduce((toplam,urun) => toplam + urun.fiyat,0);console.log("Toplam Sepet Tutarı: "+ toplamFiyat);
DOM, HTML dokümanının JavaScript tarafından okunup değiştirilebilmesini sağlayan bir ağaç yapısıdır. JavaScript ile sayfadaki yazıları, renkleri, butonları seçebilir, silebilir veya yeni dinamik elementler ekleyebiliriz.
Örnek: Bir web sayfasındaki başlık metnini arka planda kodla değiştirmek.
Uygulama: (Boş bir HTML sayfasında konsoldan denenebilir)
// Yeni bir liste elemanı oluşturma ve sayfaya eklemeconstyeniGorev= document.createElement('li');yeniGorev.innerText ="JavaScript DOM Çalışması Yapılacak";yeniGorev.className ="gorev-elemani";yeniGorev.style.color ="blue";// Sayfadaki mevcut bir elementin içine ekleme (Varsayılan bir ul gövdesine)document.body.appendChild(yeniGorev);
Kullanıcının sayfada yaptığı tıklama, klavyeye basma, formu gönderme gibi her hareket bir olaydır (Event). Olay Kabarcıklanması (Event Bubbling), tetiklenen bir olayın en alt elementten en üst elemente doğru yayılmasıdır. Olay Delegasyonu ise performans kazanmak adına etkinlik dinleyicisini alt elemanlara tek tek eklemek yerine ortak üst elemana bağlama tekniğidir.
Örnek: Listeye yeni eklenen butonların da tıklama özelliğine otomatik sahip olması delege yöntemiyle sağlanır.
Uygulama:
// Form yakalama ve sayfa yenilenmesini engelleme uygulamasıdocument.addEventListener('submit',function(etkinlik) {etkinlik.preventDefault();// Sayfa yenilenmesini durdururconsole.log("Form verileri güvenli şekilde yakalandı.");});
JavaScript tek iş parçacıklı
(single-threaded) bir dildir. Zaman alan işlemlerin (internetten
veri çekme, dosya okuma vb.) tarayıcıyı dondurmaması için
asenkron çalışır. Eskiden Callback fonksiyonları kullanılırken,
günümüzde modern Promise
yapıları ve kodu senkron gibi yazmamızı sağlayan Async/Await
blokları kullanılır. [4, 5]
Örnek: Dışarıdaki bir sunucudan (API) hava durumu verisini çekip ekrana getirme süreci.
Uygulama: (Ücretsiz bir test API'sinden veri çekme)
asyncfunctionverileriGetir() {try{console.log("Veri talep ediliyor...");// Fetch API ile istek atmaconstyanıt=awaitfetch('https://typicode.com');constveri=awaityanıt.json();console.log("Gelen Veri Başlığı:", veri.title);}catch(hata) {console.error("Veri çekilirken sorun oluştu:", hata);}}verileriGetir();
Tarayıcıların bize sunduğu, standart dilin ötesindeki donanımsal ve yazılımsal yeteneklerdir. Kullanıcının konumunu alma (Geolocation), local storage ile verileri tarayıcı hafızasına kalıcı kaydetme, Canvas ile 2D çizim yapma, ses ve video oynatma API'leri bu kapsama girer.
Örnek:
Web sitesini kapatıp açtığınızda kullanıcı adınızın veya
sepetinizdeki ürünlerin hala orada kalması localStorage
ile olur.
Uygulama:
// LocalStorage Veri Kaydetme ve OkumalocalStorage.setItem('kullaniciAdi','YazilimGelistirici');// Sayfa yenilense dahi veriyi geri çekebilirizconstsaklananIsim= localStorage.getItem('kullaniciAdi');console.log("Kayıtlı Kullanıcı:", saklananIsim);
Kod organizasyonunu nesneler
üzerinden kurgulama felsefesidir. JavaScript prototip tabanlı bir
dildir, yani nesneler yeteneklerini miras kalıtım yoluyla birbirine
aktarır. ES6 ile gelen class
(sınıf) yapısı, kapsülleme (private fields #),
getter/setter metotları OOP mimarisini standartlaştırır.
Örnek: Bir oyun projesinde yüzlerce farklı düşman karakterini tek bir ana "Düşman Sınıfı" şablonundan üretmek.
Uygulama:
classKarakter{#gizliGuc;// Private mülk (Dışarıdan erişilemez)constructor(ad,can) {this.ad = ad;this.can = can;this.#gizliGuc =100;}// Metotsaldir() {console.log(`${this.ad} hasar verdi! Kalan gizli gücü: ${this.#gizliGuc}`);}}constoyuncu1=newKarakter("Savaşçı",80);oyuncu1.saldir();// Çıktı: Savaşçı hasar verdi!
Büyük projelerde tüm kodları
tek dosyaya yazmak imkansızdır. ES Modülleri (import/export)
ile kodlar parçalara ayrılır. NPM,
harici kütüphaneleri yönetir. Babel,
yazdığımız modern kodları eski tarayıcıların da anlaması
için dönüştürür. Webpack
ise tüm bu parçaları, CSS ve görselleri tarayıcının hızlıca
okuyabileceği tek bir pakete (bundle) dönüştürür.
Örnek: Matematik fonksiyonlarını içeren ayrı bir dosyayı ana script dosyamıza dahil etmek.
Uygulama: (Teorik Dosya Yapısı Örneği)
// matematik.js dosyası içeriğiexportfunctiontopla(x,y) {returnx + y; }// ana.js dosyası içeriğiimport{topla}from'./matematik.js';console.log(topla(10,20));
İleri düzey programlamada
verilerin bellekte nasıl tutulacağını (Stacks, Queues, Linked
Lists) bilmek ve performanslı algoritmalar üretmek gerekir. Yazılan
algoritmaların doğru çalışıp çalışmadığını, gelecekte
yapılan güncellemelerin sistemi bozup bozmadığını test etmek
amacıyla Jest
kütüphanesi ile otomatik birim testleri (Unit Testing) yazılır.
Örnek: Bir kelimenin tersten okunuşu ile düz okunuşunun aynı olup olmadığını kontrol eden bir algoritmayı test etmek.
Uygulama: (Jest ile test yazım mantığı)
// KodumuzfunctionpalidromKontrol(kelime) {returnkelime === kelime.split('').reverse().join('');}// Jest Test Bloğu (Teorik Gösterim)// test('Kelime palindrom mu?', () => {// expect(palidromKontrol('kabak')).toBe(true);// });
JavaScript'in sadece tarayıcıda
değil, sunucu tarafında da (backend) çalışmasını sağlayan
çalışma ortamı Node.js'tir.
Dosya sistemi (fs)
ve internet protokolleri (http)
modülleriyle sunucular kurulur. Express
kütüphanesi yardımıyla dış dünyaya veri servis eden modern bir
REST
API
mimarisi inşa edilir. Veriler ise esnek şemaya sahip MongoDB
NoSQL
veritabanında saklanır.
Örnek: Bir mobil uygulamanın veya web sitesinin kullanıcı üyeliklerini, veri tabanına kaydeden ve kontrol eden arka plan mekanizması.
Uygulama: (Basit bir Node.js Http Sunucusu örneği)
// Node.js ortamında çalıştırılabilir temel sunucu kurulumuconsthttp= require('http');constsunucu= http.createServer((istek,yanit) => {yanit.writeHead(200, {'Content-Type':'text/plain; charset=utf-8'});yanit.end('Node.js Backend Sunucusundan Selamlar!');});// Sunucu 5000 portunda dinlemeye başlıyorsunucu.listen(5000, () => {console.log("Sunucu çalışıyor: http://localhost:5000");});
Bütün JavaScript müfredatını kapsayan, bilgisayarınızda adım adım kurup çalıştırabileceğiniz dev bir master rehber hazırladım. Bu yapı, öğrendiğiniz her konuyu tek bir çatı altında test edebilmeniz için modüler bir düzende tasarlanmıştır.
Bilgisayarınızda modern-js-master
adında bir klasör oluşturun. Klasörün iç yapısı tam olarak
aşağıdaki gibi görünmelidir:
modern-js-master/├── package.json├── webpack.config.js├── .env├── server.js└── src/├── index.html├── index.js└── modules/├── 01_konsol.js├── 02_degiskenler.js├── 03_donusumler.js├── 04_matematik_tarih.js├── 05_diziler_nesneler.js├── 06_fonksiyonlar_scope.js├── 07_akıs_donguler.js├── 08_gelişmiş_diziler.js├── 09_dom_yonetimi.js├── 10_etkinlikler.js├── 11_asenkron.js├── 12_tarayıcı_api.js├── 13_oop_siniflar.js└── 15_algoritmalar.js
Projeyi bilgisayarınızda ayağa kaldırmak için terminal veya komut satırını açıp şu komutları sırasıyla uygulayın:
1. Proje Klasörünü Oluşturun ve İçine Girin:
mkdir modern-js-mastercd modern-js-master
2. Node.js Projesini Başlatın:
npm init -y
3. Gerekli Bağımlılıkları (Paketleri) Yükleyin:
Bu
komut hem Backend (Express) hem de Frontend paketleme (Webpack,
Babel) araçlarını yükler.
npm install express dotenv corsnpm install --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin babel-loader @babel/core @babel/preset-env jest
package.json
Dosyası
Dosyanızı açın ve scripts
bölümünü aşağıdaki gibi güncelleyin:
{"name":"modern-js-master","version":"1.0.0","main":"server.js","scripts": {"frontend:dev":"webpack serve --mode development","frontend:build":"webpack --mode production","backend:start":"node server.js","test":"jest"},"dependencies": {"cors":"^2.8.5","dotenv":"^16.4.5","express":"^4.19.2"},"devDependencies": {"@babel/core":"^7.24.5","@babel/preset-env":"^7.24.5","babel-loader":"^9.1.3","html-webpack-plugin":"^5.6.0","jest":"^29.7.0","webpack":"^5.91.0","webpack-cli":"^5.1.4","webpack-dev-server":"^5.0.4"}}
webpack.config.js
DosyasıKök dizinde bu dosyayı oluşturun. Frontend kodlarımızı birleştirecektir.
constpath= require('path');constHtmlWebpackPlugin= require('html-webpack-plugin');module.exports = {entry:'./src/index.js',output: {path: path.resolve(__dirname,'dist'),filename:'bundle.js',clean:true,},plugins: [newHtmlWebpackPlugin({template:'./src/index.html',}),],module: {rules: [{test:/\.js$/,exclude:/node_modules/,use: {loader:'babel-loader',options: {presets: ['@babel/preset-env'] },},},],},devServer: {port:3000,open:true,hot:true,},};
.env
DosyasıArka plan ayarları için kök dizine ekleyin:
PORT=5000
server.js
DosyasıKursun son aşamasındaki Node.js, Express ve API mantığını çalıştıran merkez üssüdür.
constexpress= require('express');constcors= require('cors');require('dotenv').config();constapp= express();constPORT= process.env.PORT ||5000;app.use(cors());app.use(express.json());// Örnek sahte veritabanı (Müfredattaki REST API konusu için)letfikirler= [{id:1,baslik:"JavaScript Öğren",yazar:"Asım"},{id:2,baslik:"Webpack Ayarla",yazar:"Deniz"}];// GET İsteğiapp.get('/api/fikirler', (req,res) => {res.json(fikirler);});// POST İsteğiapp.post('/api/fikirler', (req,res) => {constyeniFikir= {id: Date.now(),baslik: req.body.baslik,yazar:"Anonim"};fikirler.push(yeniFikir);res.status(201).json(yeniFikir);});app.listen(PORT, () => {console.log(`Backend API çalışıyor: http://localhost:${PORT}`);});
src/index.html
DosyasıDOM ve Etkinlikler konularının tarayıcıda hayat bulacağı HTML şablonumuz.
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Modern JS Master Projesi</title><style>body { font-family: sans-serif; margin:30px; background: #f4f4f9; }.kutu { background: white; padding:20px; border-radius:8px; box-shadow:02px10px rgba(0,0,0,0.1); margin-bottom:20px; }button { padding:10px15px; background: #007bff; color: white; border: none; border-radius:4px; cursor: pointer; }button:hover { background: #0056b3; }</style></head><body><h1>Modern JavaScript Müfredat Uygulaması</h1><p>Konsolu (F12) açarak arka plandaki tüm JS çıktılarının çalışmasını izleyebilirsiniz.</p><!-- DOM ve Etkinlik Kutusu --><divclass="kutu"id="dom-kutusu"><h2id="ana-baslik">DOM ve Etkinlik Alanı</h2><buttonid="renk-butonu">Arka Plan Rengini Değiştir</button><ulid="gorev-listesi"></ul></div><!-- API Veri Kutusu --><divclass="kutu"><h2>Backend Rest API Bağlantısı</h2><buttonid="api-veri-butonu">API'den Fikirleri Çek</button><ulid="api-listesi"></ul></div></body></html>
src/index.js
DosyasıBütün JavaScript modüllerimizi (konularını) Webpack dünyasına bağlayan ana damardır.
// Müfredat konularını sırayla içeri aktarıyoruz (Modül Sistemi)import'./modules/01_konsol.js';import'./modules/02_degiskenler.js';import'./modules/03_donusumler.js';import'./modules/04_matematik_tarih.js';import'./modules/05_diziler_nesneler.js';import'./modules/06_fonksiyonlar_scope.js';import'./modules/07_akıs_donguler.js';import'./modules/08_gelişmiş_diziler.js';import'./modules/09_dom_yonetimi.js';import'./modules/10_etkinlikler.js';import'./modules/11_asenkron.js';import'./modules/12_tarayıcı_api.js';import'./modules/13_oop_siniflar.js';
src/modules/)
Aşağıdaki kodların her birini
src/modules/
klasörünün altında ilgili dosya isimleriyle oluşturun.
01_konsol.js
(Konsol Kullanımı)console.log("--- Konu 1: Konsol ---");console.warn("Bu bir uyarı mesajıdır.");console.error("Bu bir hata simülasyonudur.");
02_degiskenler.js
(Primitive vs Reference)console.log("--- Konu 2: Değişken Tipleri ---");letsayi1=10;letsayi2= sayi1;sayi1 =20;console.log("İlkel Kopya (Değişmez):", sayi2);// 10letdizi1=;letdizi2= dizi1;dizi1.push(3);console.log("Referans Kopya (Değişir!):", dizi2);// [1, 2, 3]
03_donusumler.js
(Type Conversion & Coercion)console.log("--- Konu 3: Tip Dönüşümleri ---");letmetin="100";console.log("Dönüşüm:", Number(metin) +50);// 150console.log("Dayatma (Coercion):","5"+5);// "55"
04_matematik_tarih.js
(Math & Date)console.log("--- Konu 4: Math ve Tarih ---");console.log("Rastgele Sayı (1-10):", Math.floor(Math.random() *10) +1);constbugun=newDate();console.log("Formatlı Tarih:",newIntl.DateTimeFormat('tr-TR').format(bugun));
05_diziler_nesneler.js
(Destructuring & Spread)console.log("--- Konu 5: Diziler ve Nesneler ---");constkisi= {ad:"Hasan",yas:32};const{ad} = kisi;// Destructuringconsole.log("Destructure Edilen Ad:", ad);consteskiDizi=;constyeniDizi= [...eskiDizi,3,4];// Spread Operatörüconsole.log("Birleşik Dizi:", yeniDizi);
06_fonksiyonlar_scope.js
(Arrow Functions & Scope)console.log("--- Konu 6: Fonksiyonlar ve Kapsam ---");constkaresi= (x) => x * x;// Arrow Functionconsole.log("9'un Karesi:", karesi(9));if(true) {letblokDegiskeni="Sadece buraya ait";varfonksiyonSizintisi="Blok dışına taşar";}console.log("Sızıntı Kontrolü:", fonksiyonSizintisi);
07_akıs_donguler.js
(Logic & FizzBuzz)console.log("--- Konu 7: Döngüler (FizzBuzz) ---");letsonuclar= [];for(leti=1; i <=5; i++) {if(i %3===0) sonuclar.push("Fizz");elsesonuclar.push(i);}console.log("FizzBuzz İlk 5 Adım:", sonuclar);
08_gelişmiş_diziler.js
(Map, Filter, Reduce)console.log("--- Konu 8: Gelişmiş Dizi Metotları ---");constrakamlar=;constciftler= rakamlar.filter(n => n %2===0);constkaresiDizi= rakamlar.map(n => n *2);consttoplam= rakamlar.reduce((acc,curr) => acc + curr,0);console.log("Filtre, Map, Reduce Çıktıları:", { ciftler, karesiDizi, toplam });
09_dom_yonetimi.js
(DOM Modifikasyonu)// Tarayıcı yüklenince sayfaya eleman eklerwindow.addEventListener('DOMContentLoaded', () => {constliste= document.getElementById('gorev-listesi');if(liste) {constyeniGorev= document.createElement('li');yeniGorev.innerText ="Müfredat Görevi 1: DOM Başarıyla Öğrenildi!";liste.appendChild(yeniGorev);}});
10_etkinlikler.js
(Event Listeners)window.addEventListener('DOMContentLoaded', () => {constbuton= document.getElementById('renk-butonu');constkutu= document.getElementById('dom-kutusu');if(buton && kutu) {buton.addEventListener('click', () => {kutu.style.backgroundColor = kutu.style.backgroundColor ==='bisque'?'white':'bisque';console.log("Butona tıklandı: Arka plan değişti.");});}});
11_asenkron.js
(Async / Await)console.log("--- Konu 11: Asenkron JavaScript ---");constgecikmeliVeri= () =>newPromise(resolve => setTimeout(() => resolve("Veri Geldi!"),1000));asyncfunctionakis() {console.log("İstek başladı...");constsonuc=awaitgecikmeliVeri();console.log("Asenkron Sonuç:", sonuc);}akis();
12_tarayıcı_api.js
(LocalStorage)console.log("--- Konu 12: Tarayıcı API (LocalStorage) ---");localStorage.setItem('kurs_durumu','Devam Ediyor');console.log("Kayıttan Okunan Veri:", localStorage.getItem('kurs_durumu'));
13_oop_siniflar.js
(OOP & Classes)console.log("--- Konu 13: OOP ve Sınıflar ---");classKurs{constructor(ad) {this.ad = ad;}selamla() {return`${this.ad} kursuna hoş geldiniz!`;}}constjsKursu=newKurs("Modern JavaScript 2.0");console.log(jsKursu.selamla());
src/modules/15_algoritmalar.js)Müfredattaki Unit Testing (Jest) konusunu test etmek için kök dizinde bir algoritma fonksiyonu hazırlayalım.
src/modules/15_algoritmalar.js
DosyasıfunctiontersCevir(metin) {returnmetin.split('').reverse().join('');}module.exports = tersCevir;
src/modules/15_algoritmalar.test.js
Dosyası (Test Dosyası)
Aynı klasörde .test.js
uzantılı bir dosya açın:
consttersCevir= require('./15_algoritmalar');test('Metni doğru şekilde ters çeviriyor mu?', () => {expect(tersCevir('hello')).toBe('olleh');expect(tersCevir('js')).toBe('sj');});
Her şey hazır! Şimdi 3 farklı terminal sekmesi açarak tüm sistemi tam entegre şekilde ayağa kaldırın:
Terminal 1 (Backend API Sunucusunu Başlatın):
npm run backend:start
Ekranınızda Backend
API çalışıyor: http://localhost:5000
yazacaktır.
Terminal 2 (Frontend Webpack Sunucusunu Başlatın):
npm run frontend:dev
Tarayıcınız otomatik olarak http://localhost:3000
adresinde açılacaktır. F12 tuşuna basıp Konsol (Console)
sekmesinde tüm konuların çıktılarını görebilirsiniz.
Terminal 3 (Jest Algoritma Testlerini Çalıştırın):
npm run test
Yazdığınız tersCevir
algoritmasının test edilip başarıyla geçtiğini (PASS) yeşil
renkli raporla göreceksiniz.
*******************************
Verdiğiniz kurs müfredatı belgesini satır satır ve bölüm bölüm inceleyerek, tüm konuları hiçbir özet yapmadan, en detaylı şekilde hazırladım. İstediğiniz gibi süreleri, "Önizleme" yazılarını ve "ders" satırlarını tamamen temizledim.
Bu rehber, JavaScript dilini sıfırdan ileri seviyeye kadar uygulamalarla öğrenmenizi sağlayacak dev bir kaynak niteliğindedir.
Bu kursun temel amacı, sizi sadece teorik bilgiyle bırakmak yerine JavaScript dilini gerçek projeler inşa ederek (30'dan fazla proje) öğretmektir. Kurs boyunca web sayfalarının canlandırılmasını (DOM yönetimi), modern JavaScript standartlarını (ES6+), tarayıcı hafızasını (Local Storage), internet üzerinden veri alışverişini (API, AJAX, Async/Await) ve büyük ölçekli uygulamaların mimarisini (Nesne Yönelimli Programlama - OOP) uygulamalı olarak öğreneceksiniz.
Yazılım geliştirmeye başlamak için doğru araçları kurmak ve bunları verimli kullanmayı öğrenmek gerekir.
Google Chrome Kurulumu: JavaScript kodlarının çıktısını görmek ve hataları ayıklamak için en gelişmiş geliştirici araçlarına (Developer Tools) sahip web tarayıcısıdır.
Visual Studio Code (VS-Code) Kurulumu ve İncelemesi: Günümüzde en popüler kod editörüdür. Kod yazarken bize hız ve düzen sağlar.
Live-Preview Kurulumu: Yazdığınız HTML ve JavaScript kodlarının, tarayıcıda sayfayı yenilemeye gerek kalmadan anlık olarak güncellenmesini sağlayan bir eklentidir.
Prettier Ayarları ve Kurulumu: Kodlarınızı otomatik olarak biçimlendirir. Girintileri, noktalı virgülleri ve tırnak işaretlerini sizin yerinize düzenleyerek kodun okunabilirliğini artırır.
Emmet: HTML ve CSS
kodlarını çok hızlı yazmanızı sağlayan kısa kod sistemidir.
Örneğin, editöre ul>li*3
yazıp Tab tuşuna bastığınızda otomatik olarak bir liste yapısı
oluşturur.
JavaScript dilinin en temel yapı taşları, kuralları ve veri tipleri bu bölümde işlenmektedir.
Inline JavaScript: Kodun doğrudan HTML etiketinin içerisine yazılmasıdır. Günümüzde pek tercih edilmez.
<button onclick="alert('Merhaba!')">Tıkla</button>Internal JavaScript:
Kodların HTML dosyasının içindeki <script>
etiketleri arasına yazılmasıdır.
<script>console.log("Bu bir iç JavaScript kodudur.");</script>
External JavaScript:
Kodların .js
uzantılı ayrı bir dosyada tutulması ve HTML sayfasına
bağlanmasıdır. En temiz ve profesyonel yöntemdir.
<script src="app.js"></script>Helper
Methods: Ekrana veya konsola bilgi yazdırmak için kullanılır.
console.log()
geliştiriciler için çıktı ekranıdır. alert()
kullanıcıya uyarı penceresi açar. document.write()
ise doğrudan sayfaya yazı yazar.
Statements and Comments:
Kod satırlarına ifade (statement) denir. Kodun arasına kendimiz
veya ekip arkadaşlarımız için bıraktığımız, tarayıcı
tarafından çalıştırılmayan açıklamalara ise yorum satırı
(comment) denir. Tek satır için //,
çoklu satır için /*
... */ kullanılır.
Değişkenler, program içinde verileri sakladığımız kutulardır.
İsimlendirme
Kuralları: Değişken isimleri sayıyla başlayamaz, boşluk
içeremez, özel karakterlerden sadece _
ve $
işaretlerini içerebilir. Genellikle deve tabanı (camelCase)
yöntemi tercih edilir (Örn: kullaniciAdi).
Değişken Tanımlama Yolları:
var:
Eski JavaScript sürümünden kalmadır, esnektir ancak hatalara
yol açabilir.
let:
Değeri daha sonra değiştirilebilen değişkenler için
kullanılır.
const:
Sabit değerler için kullanılır, sonradan değiştirilemez.
letyas=25;yas =26;// Geçerliconstpi=3.14;// pi = 3.15; // Hata verir!
Data Types:
JavaScript dilinde veriler temel (Primitive) ve karmaşık
(Reference) olarak ayrılır. Başlıca tipler: String
(Metin), Number
(Sayı), Boolean
(Doğru/Yanlış), Null
(Boş) ve Undefined
(Tanımlanmamış).
Quotation
Marks (Tırnak İşaretleri): Metinler tek tırnak '
', çift tırnak "
" veya eğik tırnak `
(Backtick) içinde yazılabilir.
String Concatenation (Metin
Birleştirme): Artı +
işareti kullanılarak metinler birbirine eklenir.
letisim="Ahmet";console.log("Merhaba "+ isim);// Çıktı: Merhaba Ahmet
Numbers
Basics: Sayılarla matematiksel işlemler yapmayı sağlar.
Toplama (+),
Çıkarma (-),
Çarpma (*),
Bölme (/)
ve Kalan Bulma (%
- Modulo).
Implicit Type Conversion: JavaScript'in dinamik yapısı gereği, bazen tipleri arka planda kendisi dönüştürür.
letsonuc="10"-5;// JavaScript metni sayıya çevirir. Çıktı: 5letsonuc2="10"+5;// Artı işareti birleştirme yaptığı için çıktı: "105"
Arrays (Diziler): Birden
fazla veriyi tek bir liste içinde tutmamızı sağlar. Sıralama
sıfırdan (0)
başlar.
letmeyveler= ["Elma","Armut","Muz"];console.log(meyveler[0]);// Çıktı: Elma
Functions (Fonksiyonlar):
Belirli bir işi yapan ve tekrar tekrar çağrılabilen kod
bloklarıdır. Parameter,
fonksiyon tanımlanırken parantez içine yazılan değişkenlerdir;
Argument
ise fonksiyon çağrılırken gönderilen gerçek değerlerdir.
return
anahtar kelimesi, fonksiyonun üretim sonucunu dışarıya fırlatır.
// Fonksiyon Deklarasyonu (Declaration)functiontopla(sayi1,sayi2) {returnsayi1 + sayi2;}letsonuc= topla(5,10);// 5 ve 10 argumentlerdir.
Objeler, içerisinde özellikler (property) ve metotlar (fonksiyonlar) barındıran gelişmiş yapılardır. Bir anahtar (key) ve bir değer (value) ilişkisiyle çalışır.
letaraba= {marka:"Toyota",model:"Corolla",calistir:function() { console.log("Araba çalıştı."); }};console.log(araba.marka);// Çıktı: Toyota
Conditional
Statements (Koşullar): Kodun belirli şartlara göre yön
değiştirmesini sağlar. if,
else
if ve else
kalıpları kullanılır.
Equality
(Eşitlik): ==
sadece değerleri kontrol ederken, ===
hem değeri hem de veri tipini sıkı bir şekilde kontrol eder.
Logical
Operators: Ve (&&),
Veya (||),
Değil (!)
operatörleridir.
Switch
Statement: Bir değişkenin çok sayıda farklı değere
eşitliğini kontrol etmek için if-else
yerine kullanılan daha temiz bir yapıdır.
Loops (Döngüler):
Kodların tekrar tekrar çalışmasını sağlar. while
koşul doğru olduğu sürece döner. do
while koşula bakmaksızın kodu en az bir kez
çalıştırır. for
döngüsü ise belirli bir sayıda dönmek için idealdir.
for(leti=0; i <3; i++) {console.log("Tur: "+ i);}
String
Metotları: Metinlerin uzunluğunu ölçmek (length),
harfleri büyütmek/küçültmek (toUpperCase,
toLowerCase),
metni bölmek (split)
gibi işlere yarar.
Template Literals: Eğik
tırnak `
kullanarak metinlerin içerisine kolayca değişken yerleştirmeyi
sağlar. +
işaretine gerek kalmaz.
letad="Can";console.log(`Hoş geldin ${ad}`);
Value vs Reference: Temel veri tipleri hafızada değer olarak saklanırken, objeler ve diziler referans (adres) olarak saklanır. Bir diziyi başka bir değişken kopyaladığınızda aslında adresini kopyalarsınız. Birinde yapılan değişiklik diğerini de etkiler.
Null ve
Undefined: Undefined,
bir değişkenin oluşturulduğunu ama içine henüz değer
konmadığını belirtir. Null
ise değişkenin içinin kasıtlı olarak boş bırakıldığını
ifade eder.
Truthy ve
Falsy: JavaScript'te koşul ifadesinde false
gibi davranan 6 değer vardır: false,
0,
""
(boş metin), null,
undefined,
NaN.
Bunlar dışındaki her şey true
kabul edilir.
Ternary Operator: Kısa
if-else
yazımıdır. Koşul
? Doğruysa : Yanlışsa; şeklinde yazılır.
Global vs
Local Scope: Sayfanın en üstünde tanımlanan değişken her
yerden erişilebilirdir (Global).
Bir fonksiyonun içinde tanımlanan değişken ise sadece o
fonksiyon içinden erişilebilirdir (Local).
Callback ve Higher Order
Functions: Bir fonksiyona parametre olarak gönderilen
fonksiyonlara Callback
denir. Parametre olarak fonksiyon kabul eden veya dışarıya
fonksiyon döndüren fonksiyonlara ise Higher
Order Function denir.
Diziler üzerinde dönerek verileri manipüle etmemizi sağlayan modern fonksiyonlardır.
forEach: Dizi elemanlarını tek tek dönüp işlem yapar ama yeni bir dizi oluşturmaz.
map: Dizi elemanlarını dönüştürerek yepyeni bir dizi üretir.
filter: Belirli bir şarta uyan elemanları ayıklayıp yeni bir dizi yapar.
find: Şarta uyan ilk elemanı bulur ve döndürür.
reduce: Dizi içerisindeki tüm değerleri toplayarak veya işleyerek tek bir sonuca indirger (Örn: Sepet toplamı hesabı).
DOM, tarayıcının HTML sayfasını JavaScript ile kontrol edebilmemiz için oluşturduğu bir ağaç yapısıdır. Bu bölüm sayesinde sayfadaki yazıları, renkleri ve butonları dinamik olarak değiştirebiliriz.
document.getElementById():
ID adına göre eleman seçer.
document.getElementsByTagName():
Etiket adına göre (p,
div
vb.) tüm elemanları seçer.
document.getElementsByClassName():
Klas (sınıf) adına göre elemanları bulur.
document.querySelector()
/ querySelectorAll():
CSS seçici mantığıyla tek veya çoklu eleman seçer. En esnek
yöntemdir.
DOM Navigasyonu: children
ile alt elemanlara, parentElement
ile üst elemana, nextSibling
veya nextElementSibling
ile bir sonraki kardeş elemana geçiş yapılır.
textContent
ve nodeValue:
Elemanın içindeki düz metni okur veya değiştirir.
innerHTML:
Elemanın içine HTML etiketleriyle birlikte içerik ekler.
getAttribute()
/ setAttribute():
HTML etiketlerinin özelliklerini (href,
src,
alt)
okur veya yeniden yazar.
classList
ve className:
CSS sınıflarını eklemek (add),
silmek (remove)
veya tersine çevirmek (toggle)
için kullanılır.
createElement(),
createTextNode(),
appendChild():
JavaScript ile sıfırdan bir HTML etiketi oluşturup sayfaya
eklemeyi sağlar.
insertBefore(),
replaceChild(),
removeChild():
Elemanları sırayla yerleştirmeyi, değiştirmeyi veya sayfadan
silmeyi sağlar.
Events
(Olaylar): Kullanıcının sayfada yaptığı tıklama (click),
fare hareketleri (mouseenter),
klavye tuşlamaları (keyup)
veya form gönderme (submit)
gibi hareketleri yakalar.
Event
Object & Propagation: Tıklama anında oluşan tüm
bilgileri taşıyan objedir. Olayların iç içe geçmiş
etiketlerde yukarı doğru yayılmasına Bubbling,
aşağı doğru inmesine Capturing
denir.
Local
Storage (Yerel Depolama): Sayfa yenilense veya tarayıcı
kapatılsa bile verilerin kullanıcının bilgisayarında
saklanmasını sağlar. localStorage.setItem()
ile veri yazılır, localStorage.getItem()
ile veri okunur. Objeleri saklamak için JSON.stringify(),
geri okumak için JSON.parse()
kullanılır.
Zamanlayıcılar:
setTimeout
bir kodu belirlenen süre sonunda bir kez çalıştırır.
setInterval
ise kodu her belirlenen süre zarfında durmaksızın tekrar
çalıştırır.
Sayfa Olayları:
DOMContentLoaded
HTML ağacı yüklendiğinde, load
tüm resimler dahil sayfa tamamen bittiğinde, scroll
sayfa aşağı kaydırıldığında, resize
pencere boyutu değiştiğinde tetiklenir.
Bu bölümde öğrendiğimiz tüm temeller pratik projelere dökülmektedir.
Amacı: Butona tıklandığında arka plan rengini rastgele değiştirmek.
Yapılışı: JavaScript'te
16'lık sayı sistemindeki renk kodlarını üreten bir fonksiyon
yazılır. Hex kodları karakterlerden (0-9
ve A-F)
oluşur. Math.random()
ile bu diziden rastgele 6 karakter seçilerek arka plan rengine
document.body.style.backgroundColor
ile atanır.
Amacı: Sayıyı artırıp, azaltıp sıfırlayabilen bir mekanizma yapmak.
Yapılışı: Ekranda bir
sayı ve üç buton yer alır. Butonlara tıklama olayı eklenir.
count
değişkeni artırılır veya azaltılır. Sayı 0'dan büyükse
yeşil, küçükse kırmızı, 0 ise siyah olması için style.color
kontrolü yapılır.
Amacı: Bir dizi içerisindeki müşteri verilerini (resim, isim, yorum) "İleri" ve "Geri" butonlarıyla ekranda kaydırmak.
Yapılışı: Kişi bilgileri nesnelerden oluşan bir dizide saklanır. Aktif indeks numarası tutulur. Butonlara basıldığında indeks değiştirilir ve DOM üzerindeki resim ile metin alanları güncellenir.
Amacı: Mobil uyumlu menülerin açılıp kapanmasını sağlamak.
Yapılışı: CSS'te menüyü
gizleyen bir sınıf (.hide-sidebar)
yazılır. JavaScript ile menü butonuna tıklandığında
classList.toggle('hide-sidebar')
kodu çalıştırılarak menünün yumuşakça açılması sağlanır.
Amacı: Sayfa üzerinde bir uyarı veya bilgi kutusu açmak.
Yapılışı: Butona basıldığında modalı görünür kılan CSS sınıfı eklenir, kapatma butonuna basıldığında ise o sınıf kaldırılır.
Amacı: Soru başlığına tıklandığında cevabın aşağı doğru açılması.
Yapılışı:
querySelectorAll
ile tüm sorular seçilir. Döngüyle her birine tıklama olayı
verilir. Tıklanan sorunun altındaki cevap kutusu açılırken,
diğer açık olan cevap kutuları döngüyle kapatılır
(Traversing
the DOM).
Amacı: Yemekleri kategorilerine göre (Kahvaltı, Öğle, Akşam) butonlarla filtrelemek.
Yapılışı: map
ve filter
fonksiyonları yoğun şekilde kullanılır. Benzersiz kategorileri
bulmak için new
Set() yapısından faydalanılır. Dinamik
butonlar HTML'e basılır ve filtreleme anlık gerçekleştirilir.
Amacı: Arka planda oynayan videoyu duraklatıp oynatmak ve sayfa yükleme ekranı (Preloader) yapmak.
Yapılışı: HTML5 <video>
elementinin .play()
ve .pause()
metotları bir buton vasıtasıyla tetiklenir. Sayfa tamamen
yüklendiğinde (load
olayı) yükleme ekranı gizlenir.
Amacı:
Sayfa aşağı kaydırıldığında navbar'ı sabitlemek ve menü
linklerine tıklandığında ilgili bölüme pürüzsüz kayma
(Smooth
Scroll) sağlamak.
Yapılışı:
window.pageYOffset
ile sayfanın kayma miktarı ölçülür. Belirli bir pikselden
sonra navbara .fixed-nav
sınıfı eklenir. getBoundingClientRect()
ile gidilecek elementin yüksekliği hesaplanarak tam nokta atışı
kaydırma yapılır.
Amacı: Farklı sekmelere tıklandığında alt taraftaki içeriklerin değişmesi.
Yapılışı: Tıklanan
sekme üzerindeki data-id
niteliği (attribute) okunur. Bu ID ile eşleşen içerik bloğu
görünür yapılır, diğerleri gizlenir.
Amacı: Gelecekteki bir tarihe ne kadar gün, saat, dakika ve saniye kaldığını canlı göstermek.
Yapılışı: Hedef tarihin
milisaniye değeri ile şu anki zamanın milisaniye değeri
birbirinden çıkarılır. Kalan süre matematiksel formüllerle
gün, saat ve dakikaya dönüştürülür ve setInterval
ile her saniye güncellenir.
Amacı: Kullanıcının girdiği sayı kadar rastgele paragraf üretmek.
Yapılışı: Formdan gelen
sayı değeri alınır. Elimizdeki hazır paragraf dizisinden
slice()
metodu ile o sayı kadar eleman koparılıp sayfaya basılır.
Amacı: Eleman ekleme, silme, düzenleme ve yerel hafızaya kaydetme özelliklerine sahip tam teşekküllü bir CRUD uygulaması yapmak.
Yapılışı: Form
gönderildiğinde yeni bir liste elemanı (createElement)
oluşturulur. Düzenleme butonu için ayrı, silme butonu için ayrı
olay yöneticileri atanır. Tüm liste senkronize bir şekilde Local
Storage içine yazılır, böylece sayfa yenilense de veriler
kaybolmaz.
Amacı: Resimleri veya içerikleri butonlarla sağa sola kaydırmak.
Yapılışı: Elemanlar CSS
transform:
translateX() ile yan yana dizilir. Butona
basıldığında yüzdelik değer (-100%,
-200%)
değiştirilerek kayma efekti oluşturulur.
Yaptığımız web projelerini tüm dünyanın görebileceği şekilde internete yükleme sürecidir.
Netlify Kurulumu: Statik web sitelerini ücretsiz yayınlamak için en popüler platformlardan biridir.
Drag and Drop Option: Hazırladığımız proje klasörünü sürükleyip Netlify arayüzüne bırakarak saniyeler içinde canlıya alma yöntemidir.
Continuous Deployment (Sürekli Dağıtım): GitHub gibi kod depolarına bağlayarak, kodumuzu güncellediğimiz anda web sitemizin de otomatik olarak güncellenmesini sağlayan profesyonel sistemdir.
Büyük projeleri organize etmek için kodları nesneler halinde tasarlama yaklaşımıdır.
'this'
Anahtar Kelimesi: this,
o an çalışan kodun hangi objeye ait olduğunu gösteren bir
referanstır. Global alanda tarayıcı penceresini (window)
gösterirken, bir obje içindeki metotta objenin kendisini gösterir.
Factory
Functions ve Constructor Functions: Aynı yapıya sahip birden
fazla nesne üretmek için kullanılan kalıplardır. Yapıcı
fonksiyonlar (Constructor)
new
anahtar kelimesiyle çağrılır.
Prototype Property: JavaScript'te kalıtım (miras alma) prototipler üzerinden yürür. Ortak metotlar prototipe eklenerek hafızadan (RAM) tasarruf edilir.
ES6 Class
Syntax: Modern JavaScript ile gelen, diğer dillerdeki gibi
class
(sınıf) yapısını kullanmamızı sağlayan daha temiz bir
sözdizimidir. Arka planda yine prototip mimarisini kullanır.
Call, Apply ve Bind: Bir
fonksiyonun içindeki this
kelimesinin hangi nesneyi işaret edeceğini manuel olarak
belirlememizi sağlayan özel metotlardır. bind,
fonksiyonu hemen çalıştırmaz, ileriye dönük olarak kopyasını
oluşturur.
Amacı: Temel seviyede yaptığımız sayacı nesne tabanlı mimariye dönüştürerek sayfada birden fazla bağımsız sayaç oluşturabilmek.
Yapılışı: Bir Counter
sınıfı yazılır. Constructor içinde butonlar seçilir. Sınıf
içindeki metotlar butonlara bind(this)
yapılarak bağlanır. Böylece sayfaya new
Counter(element1) ve new
Counter(element2) yazılarak iki farklı sayaç
tek kodla yönetilir.
Amacı: Sayfadaki resim gruplarına tıklandığında açılan büyük bir modal arayüzünü OOP ile inşa etmek.
Yapılışı: Galeri sınıfı, tıklanan resim listesini parametre olarak alır. Modalın açılması, kapanması, ileri ve geri fonksiyonları sınıfın birer metodu olarak atanır. Temiz ve modüler bir mimari elde edilir.
IIFE (Immediately Invoked Function Expression): Tanımlandığı an anında çalışan fonksiyonlardır. Global isim alanını kirletmemek ve değişkenleri korumak için kullanılır.
(function() { console.log("Anında çalıştım!"); })();Hoisting:
JavaScript'in değişken ve fonksiyon tanımlamalarını kod
çalışmadan önce sayfanın en üstüne taşıma davranışıdır.
var
ile tanımlanan değişkenler hoisting sebebiyle undefined
dönerken, let
ve const
hata verir.
Closure (Kapanış): Bir fonksiyonun, içinden çıktığı dış fonksiyonun kapsamındaki (scope) değişkenleri, dış fonksiyonun çalışması bitse bile hatırlaması durumudur. Veri gizliliği (private değişken oluşturma) için çok önemlidir.
JavaScript'i modern, hızlı ve az kodla yazmamızı sağlayan yeniliklerdir.
Block
Scope: let
ve const
sadece yazıldıkları süslü parantez {
} içinde yaşarlar. Buna blok kapsamı denir.
Arrow Functions: Fonksiyon
yazmanın kısa yoludur. En büyük özelliği, kendi this
bağlamına sahip olmaması, dışarıdaki this
neyse onu kullanmasıdır.
const carp = (a, b) => a * b;Destructuring (Yapı Sökme): Objelerin veya dizilerin içindeki elemanları tek hamlede çıkartıp değişkenlere atama yöntemidir.
constkisi= {ad:"Efe",yas:30};const{ad,yas} = kisi;// ad ve yas değişkenleri anında oluştu.
Spread ve
Rest Operatörleri (...):
Spread,
bir dizi veya objenin elemanlarını saçarak açar (kopyalamada
kullanılır). Rest
ise fonksiyona gelen dağınık parametreleri toplayıp bir dizi
haline getirir.
Array.from: Benzersiz yapılardan veya DOM listelerinden (NodeList) gerçek bir JavaScript dizisi türetmemizi sağlar, böylece dizi metotlarını kullanabiliriz.
Set Nesnesi
(new
Set()): İçerisinde asla tekrar
eden eleman barındırmayan özel bir koleksiyon tipidir.
includes(): Bir dizi veya
metnin içinde belirli bir elemanın geçip geçmediğini kontrol
eder, true
veya false
döndürür.
Amacı: Sayfa açıldığında istatistik sayılarının sıfırdan hedef sayıya kadar efektle yükselmesi.
Yapılışı: setInterval
kullanılarak sayılar küçük adımlarla artırılır. Hedef
sayıya ulaşıldığında zamanlayıcı temizlenir (clearInterval).
Amacı: Kullanıcının butona basarak sitenin renk temasını değiştirmesi.
Yapılışı: HTML
etiketine .dark-theme
sınıfı eklenir veya çıkarılır. CSS tarafında değişkenler
(--primary-color
vb.) bu sınıfa göre yeniden tanımlanır.
Amacı: Arama kutusuna yazılan metne ve marka butonlarına göre ürün listesini anlık süzmek.
Yapılışı: Klavyeden her
el çekildiğinde (keyup
olayı) girdiyi okuruz. products.filter()
kullanarak ürün adında bu harfler geçenleri ekrana basarız.
Kodları tek bir dev dosya yerine mantıksal küçük dosyalara bölme sistemidir.
Named
Export: Bir dosyadan birden fazla fonksiyon veya değişkeni
isimleriyle dışarı aktarma (export
const x = 5;) ve süslü parantezle içeri alma
(import
{ x } from './file.js') yöntemidir.
Default Export: Bir
dosyadan sadece tek bir ana yapıyı dışarı aktarma (export
default Yapi;) yöntemidir. İçeri alınırken
istenen isim verilebilir.
JavaScript normalde satır satır
ve sırayla çalışır (Synchronous).
Ancak internetten veri çekme gibi uzun süren işlemlerin sayfayı
dondurmaması için asenkron (Asynchronous)
çalışması gerekir.
Callback Hell: Asenkron işlemleri iç içe callback fonksiyonlarıyla yönetmeye çalışırken kodun okunamaz hale gelmesidir (merdiven yapısı).
Promises
(Sözler): Callback Hell sorununu çözmek için gelen
yapılardır. Bir işlemin gelecekte başarıyla tamamlanacağını
(Resolve)
veya hata alacağını (Reject)
temsil eden bir objedir. .then()
ve .catch()
bloklarıyla yönetilir.
Async /
Await ve Try/Catch: Promise yapılarını tamamen düz bir kod
sırasıyla yazmamızı sağlayan, günümüzdeki en modern asenkron
yönetim biçimidir. Hataları yakalamak için try
{ ... } catch (error) { ... } kalıbı
kullanılır.
AJAX, HTTP,
API kavramları: AJAX,
sayfayı yenilemeden arka planda sunucuyla veri alışverişi yapma
tekniğidir. HTTP,
bu iletişimin kurallarıdır. API
ise sunucunun bize veri sunan dış kapısıdır. Veriler çoğunlukla
JSON
formatında gelir.
Fetch API: Tarayıcıda yerleşik olarak bulunan, uzak sunuculara HTTP istekleri (veri alma/gönderme) atmamızı sağlayan modern asenkron fonksiyondur.
Artık dış dünyadaki gerçek sunuculara bağlanıp canlı veriler çektiğimiz aşamadır.
Amacı: Harici bir API sunucusuna bağlanıp her butona basıldığında yeni bir İngilizce espri getirmek.
Yapılışı: fetch()
fonksiyonu ile espri sitesinin API adresine istek atılır. Gelen
JSON verisinin içindeki espri metni DOM yoluyla ekrandaki paragraf
elementine yazdırılır. İstek esnasında yükleniyor animasyonu
gösterilir.
Amacı:
Ürünleri API'den çekip listelemek ve bir ürüne tıklandığında
onun detay sayfasına (Query
Params kullanarak) yönlendirmek.
Yapılışı: fetch
ile ürün dizisi çekilir, map
ile ekrana basılır. Her ürünün linkine ?id=123
gibi parametreler eklenir. Detay sayfasında URLSearchParams
ile bu ID okunarak sadece o ürüne ait bilgiler sunucudan istenir
ve ekrana basılır.
Amacı: Rastgele insan profilleri üreten bir API'den verileri alıp şık bir profil kartı yapmak.
Yapılışı: Gelen karmaşık veriler içerisinden isim, e-posta, telefon, harita konumu ve şifre ayrıştırılır. Fareyle ilgili ikonların üzerine gelindiğinde karttaki başlık ve içerik bilgisi dinamik olarak değişir.
Amacı: Geniş bir kokteyl veritabanında arama yapmak, detayları modal veya yeni sayfada göstermek.
Yapılışı: Arama
inputuna girilen her kelime API URL'sinin sonuna eklenerek dinamik
istek atılır (.../search.php?s=margarita).
Gelen içecekler listelenir. Bulunamazsa ekrana hata mesajı
basılır.
Kursun zirve noktası olan, tüm bilgilerin harmanlandığı büyük ölçekli projelerdir.
Amacı: İçinde kullanıcı yorumları ve puanları olan, otomatik dönen ve butonlarla da kontrol edilen kusursuz bir slayt yapısı.
Yapılışı: CSS sınıfları
(.active,
.next,
.last)
JavaScript döngüleriyle sürekli yer değiştirir. Dizinin sonuna
gelindiğinde başa, başına gelindiğinde ise en sona sarma
algoritmaları kurulur.
Amacı: Dünyaca ünlü Stripe sitesindeki gibi, farenizi menü başlığının üzerine getirdiğinizde alt menünün (submenu) onun altına yumuşakça kayarak açılması ve içeriğe göre boyut değiştirmesi.
Yapılışı: Fare
hareketleri (mouseover)
ile elementlerin konumları (getBoundingClientRect())
anlık yakalanır. Alt açılır menünün left
ve top
koordinatları ile genişliği, JavaScript tarafından dinamik
hesaplanarak CSS'e aktarılır.
Amacı: API'den gelen 100 adet veriyi tek sayfada göstermek yerine, sayfa başına 10 eleman düşecek şekilde butonlara bölmek.
Yapılışı: Gelen ana
dizi, küçük alt dizilere bölünür (Matematiksel olarak
Math.ceil(toplam
/ sayfaBasi) hesabı yapılır). Aktif sayfa
indeksine göre sadece ilgili 10 veri ekrana basılır ve alt
tarafta dinamik sayfa butonları üretilir.
Amacı: Wikipedia veritabanında anlık arama yapıp gelen sonuçları özetleri ve linkleriyle listelemek.
Yapılışı: Wikipedia'nın
resmi API protokolüne uygun CORS ayarlı fetch
istekleri atılır. Gelen HTML özet verileri güvenli bir şekilde
süzülerek arama sonuç sayfasına aktarılır.
Amacı: Gerçek hayattaki dev e-ticaret sitelerinin tüm ön yüz mekanizmasını JavaScript ile sıfırdan kurmak.
Yapılışı: Bu dev proje şu aşamalardan oluşur:
Ürünlerin
Yönetimi: API üzerinden tüm mağaza ürünleri asenkron
çekilir ve merkezi bir depoda (setupStore)
saklanır.
Çoklu Filtreleme: Kullanıcı aynı anda hem kelime araması yapabilir, hem kategoriyi seçebilir, hem de fiyat aralığı çubuğunu kaydırabilir. Üç filtre senkronize çalışır.
Sepet Mekanizması (Cart): Sepete ürün ekleme, sepet panelini sağdan kaydırarak açma, sepet içindeki ürün miktarını artırma/azaltma ve ürünü tamamen silme işlemleri yazılır.
Fiyat
Formatlama: Gelen kuruş cinsindeki veriler (1999)
düzgün para formatına ($19.99)
dönüştürülür.
Kalıcılık: Sepetteki tüm ürünler Local Storage'a kaydedilir, böylece kullanıcı ertesi gün geldiğinde sepetini bıraktığı gibi bulur. Tüm süreç baştan sona modüler JavaScript mimarisiyle inşa edilerek tamamlanır.
Müfredatta yer alan ve gerçek dünya JavaScript mantığını kurmanızı sağlayacak tüm benzersiz projeleri (tam 22 farklı uygulama mimarisini), hiçbirini atlamadan, en temel seviyeden en ileri seviyeye doğru adım adım kodlayalım.
Her projenin mantığını anlamanız için dosyaları HTML (Yapı), CSS (Görünüm) ve JavaScript (Zeka) olarak ayırarak, 4. sınıf düzeyinde bir dille, en açık şekilde hazırladım.
Mantık: Bilgisayarlar
renkleri Hex kodu adı verilen ve #
işaretiyle başlayan 6 haneli karakterlerle tanır (Örn: #FFFFFF
beyazdır). Bu projede bir butona basıldığında arka planı
rastgele boyayacağız.
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><title>Renk Değiştirici</title><linkrel="stylesheet"href="style.css"></head><body><divclass="container"><h2>Arka Plan Rengi: <spanid="renk-kodu">#FFFFFF</span></h2><buttonid="renk-btn">Rengi Değiştir</button></div><scriptsrc="app.js"></script></body></html>
body {font-family: sans-serif;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;transition: background-color0.3sease;/* Renk geçişini yumuşatır */}.container {text-align: center;background: white;padding:20px;border-radius:10px;box-shadow:04px6pxrgba(0,0,0,0.1);}button {padding:10px20px;font-size:16px;cursor: pointer;}
// 1. Kullanacağımız karakterleri bir kutuya (diziye) koyalımconsthexKarakterleri= [0,1,2,3,4,5,6,7,8,9,"A","B","C","D","E","F"];// 2. HTML'deki elemanları seçelimconstbuton= document.getElementById("renk-btn");constrenkYazisi= document.getElementById("renk-kodu");// 3. Butona tıklanınca ne olacağını yazalımbuton.addEventListener("click",function() {lethexKodu="#";// Döngü kurarak rastgele 6 karakter seçelimfor(leti=0; i <6; i++) {constrastgeleSira= Math.floor(Math.random() * hexKarakterleri.length);hexKodu += hexKarakterleri[rastgeleSira];}// Sayfanın rengini ve yazısını değiştirelimdocument.body.style.backgroundColor = hexKodu;renkYazisi.textContent = hexKodu;});
Mantık: Ekrandaki sayıyı artırıp azaltacağız. Sayı pozitifse yeşil, negatifse kırmızı, sıfırsa siyah olacak.
<divclass="sayaç-kutusu"><h1id="deger">0</h1><buttonclass="btn azalt">Azalt</button><buttonclass="btn sifirla">Sıfırla</button><buttonclass="btn artir">Artır</button></div>
letsayi=0;constdeger= document.getElementById("deger");constbutonlar= document.querySelectorAll(".btn");butonlar.forEach(function(buton) {buton.addEventListener("click",function(olay) {// Tıklanan butonun hangi sınıfa sahip olduğuna bakalımconstsiniflar= olay.currentTarget.classList;if(siniflar.contains("azalt")) {sayi--;}elseif(siniflar.contains("artir")) {sayi++;}else{sayi =0;}// Renk kontrolü yapalımif(sayi >0) { deger.style.color ="green"; }if(sayi <0) { deger.style.color ="red"; }if(sayi ===0) { deger.style.color ="black"; }deger.textContent = sayi;});});
Mantık: Elimizde müşterilerin bilgilerini içeren bir veri listesi var. İleri ve geri butonlarına basarak bu listede gezineceğiz.
// Müşteri verilerimizconstyorumlar= [{id:1,isim:"Ayşe Yılmaz",iş:"Tasarımcı",resim:"https://picsum.photos",yazi:"Harika bir hizmet, çok memnun kaldım!"},{id:2,isim:"Ahmet Kaya",iş:"Geliştirici",resim:"https://picsum.photos",yazi:"Kodlar çok temiz ve anlaşılır."}];letaktifSira=0;// Elemanları seçelimconstresim= document.getElementById("musteri-resim");constisim= document.getElementById("musteri-isim");constis= document.getElementById("musteri-is");constyazi= document.getElementById("musteri-yazi");constgeriBtn= document.querySelector(".geri-btn");constileriBtn= document.querySelector(".ileri-btn");// Ekrana veriyi basan fonksiyonfunctionmusteriGoster(sira) {consteleman= yorumlar[sira];resim.src = eleman.resim;isim.textContent = eleman.isim;is.textContent = eleman.iş;yazi.textContent = eleman.yazi;}ileriBtn.addEventListener("click",function() {aktifSira++;if(aktifSira > yorumlar.length -1) {aktifSira =0;// Başa dön}musteriGoster(aktifSira);});geriBtn.addEventListener("click",function() {aktifSira--;if(aktifSira <0) {aktifSira = yorumlar.length -1;// Sona git}musteriGoster(aktifSira);});
Mantık: CSS'te menüyü
ekranın soluna gizleyeceğiz (transform:
translateX(-100%)).
JavaScript ile butona basıldığında bir sınıf ekleyip menüyü
ekrana getireceğiz.
constmenüButonu= document.querySelector(".menu-toggle");constyanMenu= document.querySelector(".sidebar");constkapatButonu= document.querySelector(".close-btn");menüButonu.addEventListener("click",function() {// Sınıf varsa siler, yoksa ekleryanMenu.classList.toggle("show-sidebar");});kapatButonu.addEventListener("click",function() {yanMenu.classList.remove("show-sidebar");});
Mantık: Sayfanın üzerinde beliren bir bilgi kutusu (popup) yapacağız.
constacBtn= document.querySelector(".modal-btn");constkapaBtn= document.querySelector(".close-btn");constkaplama= document.querySelector(".modal-overlay");acBtn.addEventListener("click",function() {kaplama.classList.add("open-modal");});kapaBtn.addEventListener("click",function() {kaplama.classList.remove("open-modal");});
Mantık: Bir soruya tıklandığında cevabı açılacak, diğer açık olan sorular ise otomatik kapanacak.
constsorular= document.querySelectorAll(".question");sorular.forEach(function(soru) {constbuton= soru.querySelector(".question-btn");buton.addEventListener("click",function() {// Diğer açık soruları kapatma döngüsüsorular.forEach(function(item) {if(item !== soru) {item.classList.remove("show-text");}});soru.classList.toggle("show-text");});});
Mantık: Yemek listesindeki verileri kategorilere ayırıp, butonlara basıldığında sadece o kategorideki yemekleri süzüp ekrana basacağız.
constmenu= [{id:1,baslik:"Krep",kategori:"kahvalti",fiyat:45,icerik:"Harika çilekli krep."},{id:2,baslik:"Burger",kategori:"ogle",fiyat:120,icerik:"Nefis dana köfteli burger."}];constmenuAlani= document.querySelector(".section-center");constbutonAlani= document.querySelector(".btn-container");// Sayfa ilk yüklendiğinde çalışacak kodlarwindow.addEventListener("DOMContentLoaded",function() {menuyuEkranaBas(menu);kategoriButonlariHazirla();});functionmenuyuEkranaBas(menuElemanlari) {letekranHtml= menuElemanlari.map(function(item) {return`<article class="menu-item"><div class="item-info"><header><h4>${item.baslik}</h4><h4 class="price">${item.fiat} TL</h4></header><p class="item-text">${item.icerik}</p></div></article>`;});ekranHtml = ekranHtml.join("");menuAlani.innerHTML = ekranHtml;}functionkategoriButonlariHazirla() {// Benzersiz kategorileri bulalım (kahvalti, ogle vb.)constkategoriler= ["hepsi", ...newSet(menu.map(item => item.kategori))];constfiltreButonlari= kategoriler.map(function(kat) {return`<button class="filter-btn" data-id="${kat}">${kat}</button>`;}).join("");butonAlani.innerHTML = filtreButonlari;constbutonlar= butonAlani.querySelectorAll(".filter-btn");// Butonlara tıklanınca filtreleme yapalımbutonlar.forEach(function(btn) {btn.addEventListener("click",function(e) {constkategoriIsmi= e.currentTarget.dataset.id;constfiltrelenmişMenu= menu.filter(function(menuItem) {if(menuItem.kategori === kategoriIsmi) {returnmenuItem;}});if(kategoriIsmi ==="hepsi") {menuyuEkranaBas(menu);}else{menuyuEkranaBas(filtrelenmişMenu);}});});}
Mantık: Arka plan videosunu durdurup oynatacağız. Sayfa tamamen hazır olana kadar da ekranda bir yükleniyor animasyonu göstereceğiz.
constbtn= document.querySelector(".switch-btn");constvideo= document.querySelector(".video-container");constyukleniyor= document.querySelector(".preloader");// Oynat - Durdur butonubtn.addEventListener("click",function() {if(!btn.classList.contains("slide")) {btn.classList.add("slide");video.pause();// Videoyu durdur}else{btn.classList.remove("slide");video.play();// Videoyu oynat}});// Sayfa tamamen yüklendiğinde animasyonu gizlewindow.addEventListener("load",function() {yukleniyor.classList.add("hide-preloader");});
Mantık: Sayfa aşağı kayınca navbar yukarı yapışacak. Menü linklerine tıklayınca ilgili bölüme tam ölçüyle pürüzsüz kayacak.
constnavbar= document.getElementById("nav");constyukariButon= document.querySelector(".top-link");window.addEventListener("scroll",function() {constkaymaMiktari= window.pageYOffset;constnavbarYuksekligi= navbar.getBoundingClientRect().height;// Menüyü sabitleme kontrolüif(kaymaMiktari > navbarYuksekligi) {navbar.classList.add("fixed-nav");}else{navbar.classList.remove("fixed-nav");}// Yukarı çık butonunu gösterme kontrolüif(kaymaMiktari >500) {yukariButon.classList.add("show-link");}else{yukariButon.classList.remove("show-link");}});
Mantık: Hangi sekmeye tıklanırsa altındaki yazı değişecek.
constsekmeler= document.querySelector(".about");constbutonlar= document.querySelectorAll(".tab-btn");consticerikler= document.querySelectorAll(".content");sekmeler.addEventListener("click",function(e) {constid= e.target.dataset.id;if(id) {// Diğer butonlardan aktif sınıfını kaldıralımbutonlar.forEach(function(btn) {btn.classList.remove("active");});e.target.classList.add("active");// Tüm içerikleri gizleyip sadece eşleşeni açalımicerikler.forEach(function(makale) {makale.classList.remove("active");});constelement= document.getElementById(id);element.classList.add("active");}});
Mantık: Hedef bir tarihten şu anki tarihi çıkartıp kalan zamanı milisaniye cinsinden bulacağız. Sonra bunu gün, saat, dakika ve saniyeye çevireceğiz.
constzamanKutulari= document.querySelectorAll(".deadline-format h4");// Gelecekte bir hedef tarih belirleyelim (Örn: 10 gün sonrası)lethedefTarih=newDate(2027,5,25,11,30,0);consthedefMilisaniye= hedefTarih.getTime();functionkalanZamaniHesapla() {constsuAnkiMilisaniye=newDate().getTime();constkalanZaman= hedefMilisaniye - suAnkiMilisaniye;// Zaman birimlerinin milisaniye karşılıklarıconstbirGun=24*60*60*1000;constbirSaat=60*60*1000;constbirDakika=60*1000;letgun= Math.floor(kalanZaman / birGun);letsaat= Math.floor((kalanZaman % birGun) / birSaat);letdakika= Math.floor((kalanZaman % birSaat) / birDakika);letsaniye= Math.floor((kalanZaman % birDakika) /1000);constdegerler= [gun, saat, dakika, saniye];zamanKutulari.forEach(function(kutu,indeks) {kutu.textContent = degerler[indeks];});if(kalanZaman <0) {clearInterval(sayac);document.querySelector(".deadline").innerHTML =`<h4>Bu sürenin vadesi doldu!</h4>`;}}// Her saniye bu fonksiyonu tetikleyelimletsayac= setInterval(kalanZamaniHesapla,1000);kalanZamaniHesapla();
Mantık: Kullanıcı kaç adet paragraf isterse, elimizdeki listeden o kadar veriyi kesip ekrana basacağız.
constmetinler= ["Lorem ipsum dolor sit amet consectetur adipisicing elit.","Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.","Ut enim ad minim veniam, quis nostrud exercitation ullamco."];constform= document.querySelector(".lorem-form");constmiktarInput= document.getElementById("amount");constsonucAlani= document.querySelector(".lorem-text");form.addEventListener("submit",function(e) {e.preventDefault();// Sayfanın yenilenmesini engellerconstdeger= parseInt(miktarInput.value);// Girdi kontrolü yapalımif(isNaN(deger) || deger <=0|| deger > metinler.length) {constrastgeleSira= Math.floor(Math.random() * metinler.length);sonucAlani.innerHTML =`<p class="result">${metinler[rastgeleSira]}</p>`;}else{letkesilenMetinler= metinler.slice(0, deger);kesilenMetinler = kesilenMetinler.map(item =>`<p class="result">${item}</p>`).join("");sonucAlani.innerHTML = kesilenMetinler;}});
Mantık: Eleman ekleyebileceğimiz, silebileceğimiz, güncelleyebileceğimiz ve sayfayı yenilesek bile Local Storage sayesinde kaybolmayacak tam teşekküllü bir CRUD (Ekle-Oku-Güncelle-Sil) uygulaması.
<sectionclass="section-center"><formclass="grocery-form"><pclass="alert"></p><h3>Alışveriş Listesi</h3><divclass="form-control"><inputtype="text"id="grocery"placeholder="Örn: Yumurta"><buttontype="submit"class="submit-btn">Ekle</button></div></form><divclass="grocery-container"><divclass="grocery-list"></div><buttonclass="clear-btn">Listeyi Temizle</button></div></section>
constform= document.querySelector(".grocery-form");constalertYazisi= document.querySelector(".alert");constsepetInput= document.getElementById("grocery");constlisteKonteyner= document.querySelector(".grocery-container");constliste= document.querySelector(".grocery-list");consttemizleBtn= document.querySelector(".clear-btn");letduzenlemeModu=false;letduzenlenenEleman;letduzenlemeID="";// Olay Yöneticileriform.addEventListener("submit", elemanEkle);temizleBtn.addEventListener("click", listeyiTemizle);window.addEventListener("DOMContentLoaded", hafizadanYukle);functionelemanEkle(e) {e.preventDefault();constdeger= sepetInput.value;constid=newDate().getTime().toString();// Benzersiz ID üretme yoluif(deger && !duzenlemeModu) {htmlElemanOlustur(id, deger);alarmGoster("Eleman başarıyla eklendi","success");listeKonteyner.classList.add("show-container");// Yerel hafızaya eklehafizayaKaydet(id, deger);varsayılanaDon();}elseif(deger && duzenlemeModu) {duzenlenenEleman.innerHTML = deger;alarmGoster("Değer değiştirildi","success");hafizadaGuncelle(duzenlemeID, deger);varsayılanaDon();}else{alarmGoster("Lütfen bir değer giriniz!","danger");}}functionalarmGoster(metin,sinif) {alertYazisi.textContent = metin;alertYazisi.classList.add(`alert-${sinif}`);setTimeout(function() {alertYazisi.textContent ="";alertYazisi.classList.remove(`alert-${sinif}`);},2000);}functionhtmlElemanOlustur(id,deger) {constelement= document.createElement("article");element.classList.add("grocery-item");constnitelik= document.createAttribute("data-id");nitelik.value = id;element.setAttributeNode(nitelik);element.innerHTML =`<p class="title">${deger}</p><div class="btn-container"><button type="button" class="edit-btn">Düzenle</button><button type="button" class="delete-btn">Sil</button></div>`;// Silme ve Düzenleme butonlarını yakalayalımconstsilBtn= element.querySelector(".delete-btn");constduzenBtn= element.querySelector(".edit-btn");silBtn.addEventListener("click", elemanSil);duzenBtn.addEventListener("click", elemanDuzenle);liste.appendChild(element);}functionelemanSil(e) {constelement= e.currentTarget.parentElement.parentElement;constid= element.dataset.id;liste.removeChild(element);if(liste.children.length ===0) {listeKonteyner.classList.remove("show-container");}alarmGoster("Eleman silindi","danger");hafizadanSil(id);varsayılanaDon();}functionelemanDuzenle(e) {constelement= e.currentTarget.parentElement.parentElement;duzenlenenEleman = e.currentTarget.parentElement.previousElementSibling;sepetInput.value = duzenlenenEleman.innerHTML;duzenlemeModu =true;duzenlemeID = element.dataset.id;document.querySelector(".submit-btn").textContent ="Düzenle";}functionlisteyiTemizle() {constelemanlar= document.querySelectorAll(".grocery-item");if(elemanlar.length >0) {elemanlar.forEach(item => liste.removeChild(item));}listeKonteyner.classList.remove("show-container");alarmGoster("Liste temizlendi","danger");localStorage.removeItem("groceryList");varsayılanaDon();}functionvarsayılanaDon() {sepetInput.value ="";duzenlemeModu =false;duzenlemeID ="";document.querySelector(".submit-btn").textContent ="Ekle";}// LOCAL STORAGE (HAFIZA) İŞLEMLERİfunctionhafizayaKaydet(id,deger) {constgrocery= {id: id,value: deger };letelemanlar= localStorage.getItem("groceryList") ? JSON.parse(localStorage.getItem("groceryList")) : [];elemanlar.push(grocery);localStorage.setItem("groceryList", JSON.stringify(elemanlar));}functionhafizadanSil(id) {letelemanlar= JSON.parse(localStorage.getItem("groceryList"));elemanlar = elemanlar.filter(item => item.id !== id);localStorage.setItem("groceryList", JSON.stringify(elemanlar));}functionhafizadaGuncelle(id,deger) {letelemanlar= JSON.parse(localStorage.getItem("groceryList"));elemanlar = elemanlar.map(function(item) {if(item.id === id) { item.value = deger; }returnitem;});localStorage.setItem("groceryList", JSON.stringify(elemanlar));}functionhafizadanYukle() {letelemanlar= localStorage.getItem("groceryList") ? JSON.parse(localStorage.getItem("groceryList")) : [];if(elemanlar.length >0) {elemanlar.forEach(item => htmlElemanOlustur(item.id, item.value));listeKonteyner.classList.add("show-container");}}
Mantık: Resimleri CSS ile yan yana dizeceğiz. Butona tıklandığında sola veya sağa doğru kaydıracağız.
constslaytlar= document.querySelectorAll(".slide");constsonBtn= document.getElementById("nextBtn");constilkBtn= document.getElementById("prevBtn");slaytlar.forEach(function(slayt,indeks) {slayt.style.left =`${indeks *100}%`;// Resimleri yan yana dizer});letsayac=0;sonBtn.addEventListener("click",function() {sayac++;kaydir();});ilkBtn.addEventListener("click",function() {sayac--;kaydir();});functionkaydir() {// Sınırları kontrol edelimif(sayac === slaytlar.length) { sayac =0; }if(sayac <0) { sayac = slaytlar.length -1; }slaytlar.forEach(function(slayt) {slayt.style.transform =`translateX(-${sayac *100}%)`;});}
Mantık: Sayfamızda birden
çok bağımsız sayaç yapısını tek bir kalıpla (class)
üreteceğiz.
classSayac{constructor(element) {this.sayacAlani = element;this.deger =0;this.artirBtn = element.querySelector(".artir");this.azaltBtn = element.querySelector(".azalt");this.degerYazisi = element.querySelector(".deger");// This bağlamını kilitleyelimthis.artir =this.artir.bind(this);this.azalt =this.azalt.bind(this);this.artirBtn.addEventListener("click",this.artir);this.azaltBtn.addEventListener("click",this.azalt);}artir() {this.deger++;this.degerYazisi.textContent =this.deger;}azalt() {this.deger--;this.degerYazisi.textContent =this.deger;}}// Kullanımı: Sayfada iki farklı div varsa anında iki bağımsız sayaç olurconstbirinciSayac=newSayac(document.querySelector(".sayac-bir"));constikinciSayac=newSayac(document.querySelector(".sayac-iki"));
Mantık: Modüler bir yapıda, tıklandığında açılan büyük modal resim galerisi sınıfı tasarlayacağız.
classGaleri{constructor(element) {this.konteyner = element;this.liste = [...element.querySelectorAll(".img")];this.modal = document.querySelector(".modal");this.modalImg = document.querySelector(".main-img");this.kapatBtn = document.querySelector(".close-btn");this.konteyner.addEventListener("click", (e) => {if(e.target.classList.contains("img")) {this.modalAc(e.target);}});}modalAc(secilenResim) {this.modalImg.src = secilenResim.src;this.modal.classList.add("open");this.kapatBtn.addEventListener("click", () =>this.modalKapat());}modalKapat() {this.modal.classList.remove("open");}}constmutfakGaleri=newGaleri(document.querySelector(".mutfak"));
Mantık: Sayfa açılınca istatistik sayılarının sıfırdan hedef sayıya doğru hızla saymasını sağlayacağız.
constsayilar= document.querySelectorAll(".number");constsayiGuncelle= (eleman) => {consthedefDeger= parseInt(eleman.dataset.value);constartisMiktari= Math.ceil(hedefDeger /100);letbaslangic=0;constzamanlayici= setInterval(() => {baslangic += artisMiktari;if(baslangic >= hedefDeger) {eleman.textContent =`${hedefDeger}+`;clearInterval(zamanlayici);return;}eleman.textContent =`${baslangic}+`;},1);};sayilar.forEach(sayi => sayiGuncelle(sayi));
Mantık: Sitenin renk
kodlarını CSS değişkenleriyle tanımlayacağız. Butona basılınca
ana HTML etiketine .dark-theme
sınıfı basarak tüm renkleri tersine çevireceğiz.
:root {--bg-color: white;--text-color: black;}.dark-theme {--bg-color: #222;--text-color: white;}body {background-color: var(--bg-color);color: var(--text-color);}
consttemaBtn= document.querySelector(".toggle-btn");temaBtn.addEventListener("click", () => {document.documentElement.classList.toggle("dark-theme");});
Mantık: Arama çubuğuna harf yazıldıkça, ürün adlarıyla eşleşmeyen her şeyi anında ekrandan sileceğiz.
consturunler= [{isim:"Masa",marka:"Ikea"},{isim:"Sandalye",marka:"Vivense"}];constaramaInput= document.querySelector(".search-input");consturunlerKutusu= document.querySelector(".products-container");consturunleriGoster= (liste) => {urunlerKutusu.innerHTML = liste.map(u =>`<h6>${u.isim} - ${u.marka}</h6>`).join("");};aramaInput.addEventListener("keyup", () => {constarananKelime= aramaInput.value.toLowerCase();constsuzulenler= urunler.filter(u => u.isim.toLowerCase().includes(arananKelime));urunleriGoster(suzulenler);});// İlk açılışta hepsini gösterurunleriGoster(urunler);
Mantık: İnternetteki canlı bir espri sunucusuna (API) asenkron bağlanıp, gelen veriyi yakalayacağız.
consturl="https://icanhazdadjoke.com";constbtn= document.querySelector(".btn");constsonucYazisi= document.querySelector(".result");constespriGetir=async() => {sonucYazisi.textContent ="Yükleniyor...";try{// API kuralları gereği Header (başlık) bilgisi ekliyoruzconstcevap=awaitfetch(url, {headers: {Accept:"application/json"}});constveri=awaitcevap.json();sonucYazisi.textContent = veri.joke;}catch(hata) {sonucYazisi.textContent ="Bir hata oluştu!";}};btn.addEventListener("click", espriGetir);espriGetir();
Mantık: API'den gelen
verileri ana sayfada listeleyeceğiz. Bir ürüne tıklanınca
tarayıcı adres satırına ID parametresi (detay.html?id=123)
ekleyerek detay sayfasına yönlendireceğiz.
consturunlerUrl="https://course-api.com";constkonteyner= document.querySelector(".products-container");consturunleriCek=async() => {constcevap=awaitfetch(urunlerUrl);constveriler=awaitcevap.json();konteyner.innerHTML = veriler.map(urun => {const{id} = urun;const{name,price} = urun.fields;constresim= urun.fields.image[0].url;return`<a href="detay.html?id=${id}"><img src="${resim}"><footer><h5>${name}</h5><span>${price/100} TL</span></footer></a>`;}).join("");};urunleriCek();
// URL'deki ?id=... kısmını okuma yöntemiconsturlParametreleri=newURLSearchParams(window.location.search);consturunID= urlParametreleri.get("id");consttekUrunUrl=`https://course-api.com{urunID}`;consturunDetayiniGoster=async() => {constcevap=awaitfetch(tekUrunUrl);constveri=awaitcevap.json();const{name,description} = veri.fields;document.querySelector(".title").textContent = name;document.querySelector(".desc").textContent = description;};urunDetayiniGoster();
Mantık: Arama çubuğuna
yazılan içecek adını dinamik olarak API URL'sine ekleyip
(://cocktaildb.com)
canlı sonuç getireceğiz.
consturl="https://thecocktaildb.com";constform= document.querySelector(".search-form");constgirdi= document.querySelector("[name='drink']");constliste= document.querySelector(".drinks-center");constkokteylleriYukle=async(aranan) => {liste.innerHTML ="<h2>Yükleniyor...</h2>";constcevap=awaitfetch(`${url}${aranan}`);constveri=awaitcevap.json();if(!veri.drinks) {liste.innerHTML ="<h2>Aradığınız içecek bulunamadı!</h2>";return;}liste.innerHTML = veri.drinks.map(ic => {return`<article><img src="${ic.strDrinkThumb}"><h3>${ic.strDrink}</h3></article>`;}).join("");};form.addEventListener("keyup", () => {kokteylleriYukle(girdi.value);});kokteylleriYukle("a");// İlk açılışta 'a' harfi içerenleri getirir
Mantık: Fare hangi butonun
üstüne gelirse, alt menü kutusu (getBoundingClientRect)
ile o butonun altına otomatik kayıp genişleyecek.
constlinkButonlari= [...document.querySelectorAll(".link-btn")];constaltMenu= document.querySelector(".submenu");linkButonlari.forEach(btn => {btn.addEventListener("mouseover",function(e) {constbutonKonumu= e.currentTarget.getBoundingClientRect();constortaNokta= (butonKonumu.left + butonKonumu.right) /2;constaltNokta= butonKonumu.bottom -3;altMenu.style.left =`${ortaNokta}px`;altMenu.style.top =`${altNokta}px`;altMenu.classList.add("show");// Menüyü görünür yapar});});
Mantık: API'den gelen 100
adet büyük veriyi matematiksel formülle (slice)
sayfa başına 10'arlı gruplara bölüp dinamik sayfalar üreteceğiz.
consturl="https://github.com";letsayfadakiVeriler= [];letaktifSayfa=0;constsayfalariOlustur= (takipciler) => {constsayfaBasiEleman=10;consttoplamSayfaSayisi= Math.ceil(takipciler.length / sayfaBasiEleman);// Büyük diziyi küçük parçalara ayıralımconstyeniDizi= Array.from({length: toplamSayfaSayisi }, (_,indeks) => {constbaslangic= indeks * sayfaBasiEleman;returntakipciler.slice(baslangic, baslangic + sayfaBasiEleman);});returnyeniDizi;};constekranaBas= () => {constaktifGrup= sayfadakiVeriler[aktifSayfa];document.querySelector(".container").innerHTML = aktifGrup.map(t =>`<h4>${t.login}</h4>`).join("");ButonlariGoster();};constButonlariGoster= () => {letbtnHtml= sayfadakiVeriler.map((_,sira) => {return`<button class="page-btn ${sira === aktifSayfa ?'active':''}" data-index="${sira}">${sira +1}</button>`;}).join("");document.querySelector(".btn-container").innerHTML = btnHtml;};document.querySelector(".btn-container").addEventListener("click", (e) => {if(e.target.classList.contains("page-btn")) {aktifSayfa = parseInt(e.target.dataset.index);ekranaBas();}});constbaslat=async() => {constcevap=awaitfetch(url);constveriler=awaitcevap.json();sayfadakiVeriler = sayfalariOlustur(veriler);ekranaBas();};baslat();
Mantık: Kursun en büyük projesidir. Modüler mimariyle sepet yönetimini, fiyat toplamlarını ve çoklu filtreleri (Kelime + Fiyat Çubuğu + Marka) tek elden kontrol edeceğiz.
// Merkezi Depo (State)letsepet= [];leturun Deposu = [];consturunleriUzaktenCek=async() => {constcevap=awaitfetch("https://course-api.com");urunDeposu =awaitcevap.json();magazayiOlustur(urunDeposu);};// 1. Mağaza Kartlarını ÜretmefunctionmagazayiOlustur(listelenenUrunler) {constalan= document.querySelector(".products-container");alan.innerHTML = listelenenUrunler.map(u => {return`<article class="product"><img src="${u.fields.image[0].url}"><h4>${u.fields.name}</h4><p>${u.fields.price /100} TL</p><button class="add-to-cart" data-id="${u.id}">Sepete Ekle</button></article>`;}).join("");// Sepete ekleme butonlarını dinleyelimalan.querySelectorAll(".add-to-cart").forEach(btn => {btn.addEventListener("click", sepetElemanEkle);});}// 2. Sepet MantığıfunctionsepetElemanEkle(e) {constid= e.target.dataset.id;constsepette VarMi = sepet.find(item => item.id === id);if(sepetteVarMi) {sepetteVarMi.miktar++;}else{consturun= urunDeposu.find(item => item.id === id);sepet.push({id: urun.id,isim: urun.fields.name,fiyat: urun.fields.price,miktar:1});}sepetiGuncelle();}functionsepetiGuncelle() {// Toplam Fiyat ve Adet Hesaplama (Reduce ile)constsepetOzeti= sepet.reduce((toplam,item) => {toplam.para += item.fiyat * item.miktar;toplam.adet += item.miktar;returntoplam;}, {para:0,adet:0});document.querySelector(".cart-total").textContent =`${sepetOzeti.para /100} TL`;document.querySelector(".cart-items-count").textContent = sepetOzeti.adet;// Hafızayı korulocalStorage.setItem("comfySepet", JSON.stringify(sepet));}// 3. Çoklu Fiyat ve Filtre Çubuğu KontrolüconstfiyatCubugu= document.querySelector(".price-filter");fiyatCubugu.addEventListener("input", () => {constmaxFiyat= fiyatCubugu.value;constfiltrelenmis= urunDeposu.filter(u => (u.fields.price /100) <= maxFiyat);magazayiOlustur(filtrelenmis);});// Başlangıç Ayarlarıwindow.addEventListener("DOMContentLoaded", () => {sepet = localStorage.getItem("comfySepet") ? JSON.parse(localStorage.getItem("comfySepet")) : [];urunleriUzaktenCek();sepetiGuncelle();});
Bilgisayarınızda
bir klasör oluşturun (Örn: JavaScriptProjeleri).
İçine her
uygulama için yeni bir klasör açın (renk-degistirici,
alisveris-sepeti
vb.).
İlgili kodları index.html,
style.css
ve app.js
isimleriyle kaydedip kod editörünüzdeki (VS Code) Live Preview
veya Live Server butonuna basarak tarayıcıda canlı olarak
test edin.
==============================================================================================
Müfredatta yer alan tüm temel, orta ve ileri düzey projelerin arayüzlerini modern standartlara taşımak için gelişmiş CSS mimarileri (CSS Variables, Flexbox, Grid, Glassmorphism ve gelişmiş animasyonlar) ekledim.
Tasarımların birbirini bozmaması için her projenin HTML, CSS ve JavaScript kodlarını kendi içinde tam uyumlu ve eksiksiz olacak şekilde baştan aşağı yeniledim.
Tasarım Detayı: Arka plana uyum sağlayan, yarı saydam ve arkasını bulandıran modern bir cam efekti (Glassmorphism) kart tasarımı eklenmiştir.
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Modern Renk Değiştirici</title><linkrel="stylesheet"href="style.css"></head><body><divclass="glass-card"><h2>Arka Plan Rengi: <spanid="color-code">#6366F1</span></h2><buttonid="flip-btn">Rengi Rastgele Değiştir</button></div><scriptsrc="app.js"></script></body></html>
:root {--transition-speed:0.4s;}body {font-family:'Segoe UI', system-ui, sans-serif;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;background: linear-gradient(135deg, #6366f1, #a855f7);transition: background var(--transition-speed) ease;}.glass-card {background: rgba(255,255,255,0.2);backdrop-filter: blur(15px);-webkit-backdrop-filter: blur(15px);border:1pxsolid rgba(255,255,255,0.3);padding:2.5rem;border-radius:20px;box-shadow:08px32px0rgba(0,0,0,0.2);text-align: center;color: #ffffff;}h2 {margin-bottom:2rem;font-size:1.8rem;letter-spacing:1px;}#color-code {background: rgba(0,0,0,0.3);padding:0.3rem0.8rem;border-radius:8px;font-family: monospace;font-weight: bold;}button {background: #ffffff;color: #4f46e5;border: none;padding:0.8rem1.8rem;font-size:1rem;font-weight:600;border-radius:10px;cursor: pointer;transition: all0.3sease;box-shadow:04px15pxrgba(0,0,0,0.1);}button:hover {transform: translateY(-3px);box-shadow:06px20pxrgba(0,0,0,0.2);background: #f3f4f6;}button:active {transform: translateY(-1px);}
consthex= [0,1,2,3,4,5,6,7,8,9,"A","B","C","D","E","F"];constbtn= document.getElementById("flip-btn");constcolor= document.getElementById("color-code");btn.addEventListener("click", () => {lethexColor="#";for(leti=0; i <6; i++) {hexColor += hex[Math.floor(Math.random() * hex.length)];}color.textContent = hexColor;document.body.style.background = hexColor;});
Tasarım Detayı: Butonlara ve ana ekrana yumuşak gölgelerle gömülme ve kabarma hissi veren Neumorphic tasarım dili uygulanmıştır.
<divclass="neumorphic-counter"><divclass="display-box"><h1id="value">0</h1></div><divclass="btn-group"><buttonclass="control-btn decrease">Azalt</button><buttonclass="control-btn reset">Sifirla</button><buttonclass="control-btn increase">Artir</button></div></div>
body {background-color: #e0e0e0;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;font-family:'Segoe UI', sans-serif;}.neumorphic-counter {background: #e0e0e0;padding:3rem;border-radius:30px;box-shadow:15px15px30px#bebebe,-15px15px30px#ffffff;text-align: center;}.display-box {background: #e0e0e0;padding:1.5rem;border-radius:20px;box-shadow: inset7px7px14px#bebebe, inset-7px-7px14px#ffffff;margin-bottom:2rem;}#value {font-size:4rem;margin:0;color: #333;transition: color0.3sease;}.btn-group {display: flex;gap:1rem;}.control-btn {border: none;background: #e0e0e0;padding:1rem1.5rem;font-size:1rem;font-weight:600;border-radius:12px;cursor: pointer;color: #666;box-shadow:5px5px10px#bebebe,-5px-5px10px#ffffff;transition: all0.2sease;}.control-btn:hover {color: #333;}.control-btn:active {box-shadow: inset3px3px6px#bebebe, inset-3px-3px6px#ffffff;}
letcount=0;constvalue= document.getElementById("value");constbtns= document.querySelectorAll(".control-btn");btns.forEach((btn) => {btn.addEventListener("click", (e) => {conststyles= e.currentTarget.classList;if(styles.contains("decrease")) {count--;}elseif(styles.contains("increase")) {count++;}else{count =0;}if(count >0) value.style.color ="#10B981";if(count <0) value.style.color ="#EF4444";if(count ===0) value.style.color ="#333333";value.textContent = count;});});
Tasarım Detayı: Yuvarlatılmış profil resmi, şık tırnak işaretleri arka planı ve pürüzsüz geçiş sağlayan buton animasyonları eklenmiştir.
body {background-color: #f1f5f9;font-family: sans-serif;display: flex;justify-content: center;align-items: center;height:100vh;margin:0;}.review-card {background: #ffffff;padding:2.5rem;border-radius:16px;box-shadow:010px25px-5pxrgba(0,0,0,0.1);max-width:500px;width:90%;text-align: center;position: relative;}.img-container {width:120px;height:120px;border-radius:50%;margin:0auto1.5rem;position: relative;background: #10b981;}.img-container img {width:100%;height:100%;border-radius:50%;object-fit: cover;position: relative;z-index:1;}.img-container::before {content:'';position: absolute;top:-4px;right:-4px;width:100%;height:100%;border-radius:50%;background: #6366f1;}#author {margin:0;font-size:1.25rem;color: #1e293b;}#job {text-transform: uppercase;color: #6366f1;font-size:0.85rem;font-weight:600;margin-bottom:1rem;display: inline-block;}#info {color: #64748b;line-height:1.6;}.nav-container {margin-top:1.5rem;}.nav-btn {background: none;border: none;font-size:1.5rem;color: #6366f1;cursor: pointer;margin:00.5rem;transition: color0.2s;}.nav-btn:hover {color: #4f46e5;}
Tasarım Detayı: Sol
taraftan kayarak gelen, gölgelendirmeli ve ekranı karartan arka
plan kaplamalı (overlay)
mobil uyumlu tasarım.
.sidebar {position: fixed;top:0;left:0;width:300px;height:100%;background: #ffffff;box-shadow:5px025pxrgba(0,0,0,0.1);transform: translateX(-100%);transition: transform0.3scubic-bezier(0.4,0,0.2,1);z-index:999;padding:2rem;}.show-sidebar {transform: translateX(0);}.sidebar-header {display: flex;justify-content: space-between;align-items: center;border-bottom:1pxsolid #f1f5f9;padding-bottom:1rem;}.close-btn {font-size:2rem;background: transparent;border: none;color: #ef4444;cursor: pointer;}.links a {display: block;padding:1rem;color: #334155;text-decoration: none;font-size:1.1rem;border-radius:8px;transition: background0.2s;}.links a:hover {background: #f8fafc;color: #6366f1;}
Tasarım Detayı: Arka planı
karartıp, modal penceresini yukarıdan aşağıya doğru
ölçeklenerek (transform:
scale)
getiren pürüzsüz animasyon.
.modal-overlay {position: fixed;top:0;left:0;width:100%;height:100%;background: rgba(15,23,42,0.6);display: grid;place-items: center;opacity:0;pointer-events: none;transition: opacity0.3sease;z-index:1000;}.open-modal {opacity:1;pointer-events: auto;}.modal-container {background: #ffffff;padding:3rem;border-radius:16px;max-width:500px;width:90%;text-align: center;position: relative;transform: translateY(-30px) scale(0.9);transition: transform0.3scubic-bezier(0.34,1.56,0.64,1);}.open-modal .modal-container {transform: translateY(0) scale(1);}
Tasarım Detayı: Soruların ve cevapların yumuşak yükseklik geçişi ve aktif kartın kenar çizgisi renginin değişmesi sağlandı.
.question {background: #ffffff;border:2pxsolid #e2e8f0;border-radius:12px;padding:1.5rem;margin-bottom:1rem;transition: all0.3sease;}.question.show-text {border-color: #6366f1;box-shadow:04px20pxrgba(99,102,241,0.1);}.question-title {display: flex;justify-content: space-between;align-items: center;cursor: pointer;}.question-text {max-height:0;overflow: hidden;transition: max-height0.3sease-out;color: #475569;line-height:1.6;}.question.show-text .question-text {max-height:200px;margin-top:1rem;border-top:1pxsolid #f1f5f9;padding-top:1rem;}
Tasarım Detayı: CSS Grid
mimarisi ile duyarlı (responsive)
kart dizilimi ve kategori butonlarına özel aktif durum efektleri
eklendi.
.btn-container {display: flex;justify-content: center;gap:1rem;margin-bottom:3rem;}.filter-btn {background: transparent;border:2pxsolid #6366f1;color: #6366f1;padding:0.5rem1.2rem;border-radius:30px;font-weight:600;cursor: pointer;transition: all0.2s;}.filter-btn:hover, .filter-btn.active {background: #6366f1;color: #ffffff;}.section-center {display: grid;grid-template-columns: repeat(auto-fit, minmax(350px,1fr));gap:2rem;width:90vw;max-width:1170px;margin:0auto;}.menu-item {background: #ffffff;border-radius:12px;overflow: hidden;box-shadow:04px6px-1pxrgba(0,0,0,0.05);}.item-info {padding:1.5rem;}header {display: flex;justify-content: space-between;border-bottom:0.5pxdashed #cbd5e1;padding-bottom:0.5rem;margin-bottom:1rem;}.price {color: #6366f1;}
Tasarım Detayı: Tam ekran
arka plan videosu katmanı, kaydırmalı buton tasarımı (toggle
switch)
ve dönen yükleme halkası animasyonu.
.preloader {position: fixed;top:0; left:0; right:0; bottom:0;background: #ffffff;z-index:9999;display: grid;place-items: center;transition: opacity0.3s;}.hide-preloader {opacity:0;pointer-events: none;}.spinner {width:50px;height:50px;border:5pxsolid #e2e8f0;border-top-color: #6366f1;border-radius:50%;animation: spin1slinear infinite;}@keyframesspin {to{ transform: rotate(360deg); }}.switch-btn {position: absolute;bottom:7%; left:7%;width:7rem; height:2.5rem;background: #6366f1;border-radius:30px;border: none;cursor: pointer;display: flex;align-items: center;justify-content: space-between;padding:00.5rem;}.switch-btn span {color: #fff; font-size:0.8rem; font-weight: bold;}.switch-style {position: absolute;top:0; left:0;width:50%; height:100%;background: #ffffff;border-radius:30px;transition: transform0.2slinear;}.slide .switch-style {transform: translateX(100%);}
Tasarım Detayı: Sayfa
aşağı indikçe camlaşan (blur)
ve daralan yapışkan menü (sticky
navbar)
tasarımı.
nav {position: absolute;top:0; left:0; width:100%;padding:1.5rem0;transition: all0.3sease;z-index:100;}.fixed-nav {position: fixed;background: rgba(255,255,255,0.8);backdrop-filter: blur(10px);padding:0.8rem0;box-shadow:04px20pxrgba(0,0,0,0.05);}.top-link {position: fixed;bottom:2rem; right:-5rem;background: #6366f1;color: white;width:3rem; height:3rem;border-radius:50%;display: grid;place-items: center;transition: all0.3sease;}.show-link {right:2rem;}
Tasarım Detayı: Sekmeler arası geçişlerde solma ve aktif tab çizgisinin vurgulanması sağlandı.
.tab-btn {padding:1rem2rem;border: none;background: #f8fafc;cursor: pointer;font-size:1rem;font-weight:600;color: #64748b;border-bottom:2pxsolid transparent;transition: all0.2s;}.tab-btn.active {background: #ffffff;color: #6366f1;border-bottom-color: #6366f1;}.content {display: none;padding:2rem;background: #ffffff;animation: fadeIn0.4sease;}.content.active {display: block;}@keyframesfadeIn {from{ opacity:0; transform: translateY(5px); }to{ opacity:1; transform: translateY(0); }}
Tasarım Detayı: Koyu gri neon detaylı kartlar ile zaman birimlerinin modern kutular içinde gösterimi.
.countdown-container {display: flex;gap:1.5rem;justify-content: center;margin-top:2rem;}.deadline-format {background: #1e293b;color: #ffffff;padding:1.5rem;border-radius:16px;width:90px;text-align: center;box-shadow:010px15px-3pxrgba(0,0,0,0.1);}.deadline-format h4 {font-size:2.5rem;margin:0;color: #38bdf8;font-family: monospace;}.deadline-format span {font-size:0.8rem;text-transform: uppercase;color: #94a3b8;letter-spacing:1px;}
Tasarım Detayı: Temiz
girdi (input)
alanı, animasyonlu form butonu ve gölgeli paragraf çıktı
blokları.
.lorem-form {display: flex;gap:1rem;justify-content: center;align-items: center;}input[type="number"] {padding:0.75rem;border:2pxsolid #cbd5e1;border-radius:8px;width:80px;font-size:1rem;}input[type="number"]:focus {outline: none;border-color: #6366f1;}.result p {background: #ffffff;padding:1.5rem;border-radius:12px;margin-bottom:1rem;box-shadow:02px4pxrgba(0,0,0,0.02);border-left:4pxsolid #6366f1;}
Tasarım Detayı: Listeye eklenen elemanların sağa doğru kayarak gelmesi ve silerken solması için gelişmiş liste animasyonları ve şık buton tasarımları.
<sectionclass="grocery-app"><formclass="grocery-form"><pclass="alert"></p><h3>Mutfak Alisverisi</h3><divclass="input-group"><inputtype="text"id="grocery"placeholder="Örn: Süt al..."><buttontype="submit"class="submit-btn">Ekle</button></div></form><divclass="grocery-container"><divclass="grocery-list"></div><buttonclass="clear-btn">Listeyi Temizle</button></div></section>
body {background-color: #f8fafc;font-family:'Segoe UI', sans-serif;display: grid;place-items: center;height:100vh;margin:0;}.grocery-app {background: #ffffff;padding:2.5rem;border-radius:20px;box-shadow:020px25px-5pxrgba(0,0,0,0.05);width:90vw;max-width:450px;}.input-group {display: flex;gap:0.5rem;}#grocery {flex:1;padding:0.8rem1rem;border:2pxsolid #e2e8f0;border-radius:10px;font-size:1rem;transition: border-color0.2s;}#grocery:focus {outline: none;border-color: #6366f1;}.submit-btn {background: #6366f1;color: white;border: none;padding:01.5rem;border-radius:10px;font-weight:600;cursor: pointer;}.grocery-item {display: flex;justify-content: space-between;align-items: center;padding:0.75rem1rem;background: #f8fafc;margin-top:1rem;border-radius:8px;animation: slideIn0.3sease;}@keyframesslideIn {from{ opacity:0; transform: translateX(-10px); }to{ opacity:1; transform: translateX(0); }}.alert {padding:0.5rem;border-radius:6px;text-align: center;font-size:0.9rem;font-weight:500;}.alert-success { background: #dcfce7; color: #15803d; }.alert-danger { background: #fee2e2; color: #b91c1c; }
constform= document.querySelector(".grocery-form");constalertYazisi= document.querySelector(".alert");constsepetInput= document.getElementById("grocery");constlisteKonteyner= document.querySelector(".grocery-container");constliste= document.querySelector(".grocery-list");consttemizleBtn= document.querySelector(".clear-btn");letduzenlemeModu=false;letduzenlenenEleman;letduzenlemeID="";form.addEventListener("submit", elemanEkle);temizleBtn.addEventListener("click", listeyiTemizle);window.addEventListener("DOMContentLoaded", hafizadanYukle);functionelemanEkle(e) {e.preventDefault();constdeger= sepetInput.value;constid=newDate().getTime().toString();if(deger && !duzenlemeModu) {htmlElemanOlustur(id, deger);alarmGoster("Eleman basariyla eklendi","success");listeKonteyner.classList.add("show-container");hafizayaKaydet(id, deger);varsayılanaDon();}elseif(deger && duzenlemeModu) {duzenlenenEleman.innerHTML = deger;alarmGoster("Deger degistirildi","success");hafizadaGuncelle(duzenlemeID, deger);varsayılanaDon();}else{alarmGoster("Lütfen bir deger giriniz!","danger");}}functionalarmGoster(metin,sinif) {alertYazisi.textContent = metin;alertYazisi.className =`alert alert-${sinif}`;setTimeout(() => {alertYazisi.textContent ="";alertYazisi.className ="alert";},2000);}functionhtmlElemanOlustur(id,deger) {constelement= document.createElement("article");element.classList.add("grocery-item");element.setAttribute("data-id", id);element.innerHTML =`<p class="title">${deger}</p><div class="btn-group"><button type="button" class="edit-btn" style="color: #6366f1; border:none; background:none; cursor:pointer;">Duzenle</button><button type="button" class="delete-btn" style="color: #ef4444; border:none; background:none; cursor:pointer; margin-left:10px;">Sil</button></div>`;element.querySelector(".delete-btn").addEventListener("click", elemanSil);element.querySelector(".edit-btn").addEventListener("click", elemanDuzenle);liste.appendChild(element);}functionelemanSil(e) {constelement= e.currentTarget.parentElement.parentElement;constid= element.dataset.id;liste.removeChild(element);if(liste.children.length ===0) listeKonteyner.classList.remove("show-container");alarmGoster("Eleman silindi","danger");hafizadanSil(id);varsayılanaDon();}functionelemanDuzenle(e) {constelement= e.currentTarget.parentElement.parentElement;duzenlenenEleman = e.currentTarget.parentElement.previousElementSibling;sepetInput.value = duzenlenenEleman.innerHTML;duzenlemeModu =true;duzenlemeID = element.dataset.id;form.querySelector(".submit-btn").textContent ="Duzenle";}functionlisteyiTemizle() {constelemanlar= document.querySelectorAll(".grocery-item");if(elemanlar.length >0) elemanlar.forEach(item => liste.removeChild(item));listeKonteyner.classList.remove("show-container");alarmGoster("Liste temizlendi","danger");localStorage.removeItem("groceryList");varsayılanaDon();}functionvarsayılanaDon() {sepetInput.value ="";duzenlemeModu =false;duzenlemeID ="";form.querySelector(".submit-btn").textContent ="Ekle";}functionhafizayaKaydet(id,deger) {letelemanlar= localStorage.getItem("groceryList") ? JSON.parse(localStorage.getItem("groceryList")) : [];elemanlar.push({ id,value: deger });localStorage.setItem("groceryList", JSON.stringify(elemanlar));}functionhafizadanSil(id) {letelemanlar= JSON.parse(localStorage.getItem("groceryList"));elemanlar = elemanlar.filter(item => item.id !== id);localStorage.setItem("groceryList", JSON.stringify(elemanlar));}functionhafizadaGuncelle(id,deger) {letelemanlar= JSON.parse(localStorage.getItem("groceryList"));elemanlar = elemanlar.map(item => {if(item.id === id) item.value = deger;returnitem;});localStorage.setItem("groceryList", JSON.stringify(elemanlar));}functionhafizadanYukle() {letelemanlar= localStorage.getItem("groceryList") ? JSON.parse(localStorage.getItem("groceryList")) : [];if(elemanlar.length >0) {elemanlar.forEach(item => htmlElemanOlustur(item.id, item.value));listeKonteyner.classList.add("show-container");}}
Tasarım Detayı: Ekranı kaplayan, yumuşak kayma efektine sahip ok butonlu minimalist galeri geçişi.
.slider-container {position: relative;width:80vw; height:50vh;margin:0auto;overflow: hidden;border-radius:16px;box-shadow:020px25px-5pxrgba(0,0,0,0.1);}.slide {position: absolute;width:100%; height:100%;transition: transform0.5scubic-bezier(0.77,0,0.175,1);}.btn-container {position: absolute;top:50%; transform: translateY(-50%);width:100%; display: flex;justify-content: space-between;padding:01rem; box-sizing: border-box;z-index:10;}
Tasarım Detayı: Sayfada yan yana duran, bağımsız renk temalarına sahip dinamik sayaç kart mimarisi.
.sayac-kart {background: #ffffff;border-radius:16px;padding:2rem;box-shadow:010px15px-3pxrgba(0,0,0,0.05);text-align: center;width:200px;}.deger {font-size:3rem;font-weight:800;margin:1rem0;}
Tasarım Detayı: Resimlerin üzerine gelindiğinde parlayan, tıklandığında ekranı kaplayan koyu temalı premium Lightbox modal penceresi.
.gallery-center {display: grid;grid-template-columns: repeat(auto-fill, minmax(250px,1fr));gap:1.5rem;padding:2rem;}.img {width:100%; height:200px;object-fit: cover;border-radius:12px;cursor: pointer;transition: transform0.3s, filter0.3s;}.img:hover {transform: scale(1.03);filter: brightness(0.9);}.modal.open {display: grid;place-items: center;position: fixed;top:0; left:0; width:100%; height:100%;background: rgba(0,0,0,0.9);z-index:10000;}
Tasarım Detayı: Modern
veri analiz panellerindeki (dashboard)
gibi parlayan neon yeşil istatistik sayıları.
.number-card {background: #0f172a;border:1pxsolid #1e293b;padding:2.5rem;border-radius:16px;text-align: center;min-width:180px;}.number {font-size:3.5rem;color: #10b981;font-weight: bold;text-shadow:0020pxrgba(16,185,129,0.4);}
Tasarım Detayı: Sadece arka planı değil, kart gölgelerini ve yazı renklerini gözü yormayacak derin gri tona çeken sistem.
:root {--bg: #f8fafc;--card: #ffffff;--text: #0f172a;}.dark-theme {--bg: #0f172a;--card: #1e293b;--text: #f8fafc;}body { background: var(--bg); color: var(--text); transition: all0.3s; }.card { background: var(--card); }
Tasarım Detayı:
Filtrelenen ürün sayılarını ve markaları şık rozetlerle
(badge)
gösteren temiz liste düzeni.
.search-input {width:100%; padding:1rem;border-radius:30px;border:2pxsolid #cbd5e1;font-size:1.1rem;}.product-badge {background: #e0f2fe;color: #0369a1;padding:0.25rem0.5rem;border-radius:6px;font-size:0.8rem;}
Tasarım Detayı: Gelen esprileri mesajlaşma uygulamasındaki sohbet balonuna yerleştiren sevimli tasarım.
.joke-bubble {background: #e0e7ff;color: #3730a3;padding:1.5rem2rem;border-radius:20px20px20px0;font-size:1.2rem;position: relative;box-shadow:04px6pxrgba(0,0,0,0.05);}
Tasarım Detayı: İnternetten çekilen ürün görsellerini pürüzsüz kartlara oturtup, fiyat etiketlerini belirginleştiren arayüz.
.products-container {display: grid;grid-template-columns: repeat(auto-fill, minmax(280px,1fr));gap:2rem;}.product-card {background: white;border-radius:12px;overflow: hidden;box-shadow:04px10pxrgba(0,0,0,0.05);}.product-card img {width:100%; height:220px; object-fit: cover;}
Tasarım Detayı: Kokteyl tarifleri için resmin altına degrade karartma eklenmiş yarı transparan isim etiketleri.
.cocktail-card {position: relative;border-radius:16px;overflow: hidden;}.cocktail-title {position: absolute;bottom:0; left:0; width:100%;background: linear-gradient(transparent, rgba(0,0,0,0.8));color: white; padding:1rem;}
Tasarım Detayı: Fare butonların üzerinde gezdikçe alt menü kutusunun bir baloncuk gibi sola-sağa kayarak boyut değiştirmesi.
.submenu {position: absolute;background: #ffffff;border-radius:10px;box-shadow:050px100px-20pxrgba(50,50,93,0.25);display: none;padding:1.5rem;transform: translateX(-50%);transition: all0.25scubic-bezier(0.075,0.82,0.165,1);}.submenu.show { display: block; }
Tasarım Detayı: Aktif sayfayı parlak mavi renkle belirten, kenarları yuvarlatılmış kare sayfalama buton kümesi.
.page-btn {width:40px; height:40px;border: none; background: #e2e8f0;margin:05px; border-radius:8px;font-weight: bold; cursor: pointer;}.page-btn.active {background: #6366f1; color: white;}
Tasarım Detayı: E-ticaret
sitelerindeki gibi sağ taraftan kayarak gelen gölgeli sepet
çekmecesi (sliding
cart panel)
ve dinamik listeleme alanı.
<navclass="shop-nav"><divclass="nav-center"><h2>Comfy Mağazasi</h2><divclass="cart-btn-container"><buttonclass="toggle-cart-btn">Sepet (<spanclass="cart-items-count">0</span>)</button></div></div></nav><mainclass="shop-container"><asideclass="sidebar-filters"><h4>Filtreler</h4><inputtype="range"class="price-filter"min="0"max="200"value="200"><p>Maksimum Fiyat: <spanclass="price-value">200</span> TL</p></aside><sectionclass="products-container"></section></main><!-- Sağdan Kayarak Açılan Sepet Çekmecesi --><divclass="cart-overlay"><asideclass="cart-sidebar"><buttonclass="close-cart">Kapat</button><h3>Sepetiniz</h3><divclass="cart-content"></div><divclass="cart-footer"><h4>Toplam: <spanclass="cart-total">0TL</span></h4></div></aside></div>
body {font-family:'Segoe UI', sans-serif;margin:0; background: #f8fafc;}.shop-nav {background: #ffffff; padding:1.5rem;box-shadow:02px5pxrgba(0,0,0,0.05);}.nav-center {display: flex; justify-content: space-between;max-width:1100px; margin:0auto;}.shop-container {display: grid; grid-template-columns:250px1fr;max-width:1100px; margin:2remauto; gap:2rem;}.products-container {display: grid; grid-template-columns: repeat(auto-fill, minmax(250px,1fr));gap:1.5rem;}/* Sepet Çekmecesi CSS Mimari Kodları */.cart-overlay {position: fixed; top:0; right:0; width:100%; height:100%;background: rgba(15,23,42,0.5);z-index:9999; visibility: hidden; opacity:0;transition: all0.3sease;}.cart-overlay.show { visibility: visible; opacity:1; }.cart-sidebar {position: fixed; top:0; right:-400px; width:380px; height:100%;background: #ffffff; padding:2rem; box-sizing: border-box;box-shadow:-5px030pxrgba(0,0,0,0.15);transition: right0.3scubic-bezier(0.4,0,0.2,1);}.cart-overlay.show .cart-sidebar { right:0; }
letsepet= [];leturunDeposu= [];constsepetOverlay= document.querySelector(".cart-overlay");constsepetAcBtn= document.querySelector(".toggle-cart-btn");constsepetKapatBtn= document.querySelector(".close-cart");sepetAcBtn.addEventListener("click", () => sepetOverlay.classList.add("show"));sepetKapatBtn.addEventListener("click", () => sepetOverlay.classList.remove("show"));consturunleriUzaktenCek=async() => {constcevap=awaitfetch("https://course-api.com");urunDeposu =awaitcevap.json();magazayiOlustur(urunDeposu);};functionmagazayiOlustur(listelenenUrunler) {constalan= document.querySelector(".products-container");alan.innerHTML = listelenenUrunler.map(u => {return`<article style="background:#fff; padding:1rem; border-radius:12px; box-shadow:0 4px 6px rgba(0,0,0,0.02)"><img src="${u.fields.image.url}" style="width:100%; height:180px; object-fit:cover; border-radius:8px;"><h4 style="margin:0.5rem 0">${u.fields.name}</h4><p style="color:#6366f1; font-weight:bold">${u.fields.price /100} TL</p><button class="add-to-cart" data-id="${u.id}" style="background:#6366f1; color:white; border:none; padding:0.5rem 1rem; border-radius:6px; cursor:pointer; width:100%">Sepete Ekle</button></article>`;}).join("");alan.querySelectorAll(".add-to-cart").forEach(btn => {btn.addEventListener("click", sepetElemanEkle);});}functionsepetElemanEkle(e) {constid= e.target.dataset.id;constsepetteVarMi= sepet.find(item => item.id === id);if(sepetteVarMi) {sepetteVarMi.miktar++;}else{consturun= urunDeposu.find(item => item.id === id);sepet.push({id: urun.id,isim: urun.fields.name,fiyat: urun.fields.price,miktar:1});}sepetiGuncelle();}functionsepetiGuncelle() {constsepetOzeti= sepet.reduce((toplam,item) => {toplam.para += item.fiyat * item.miktar;toplam.adet += item.miktar;returntoplam;}, {para:0,adet:0});document.querySelector(".cart-total").textContent =`${sepetOzeti.para /100} TL`;document.querySelector(".cart-items-count").textContent = sepetOzeti.adet;localStorage.setItem("comfySepet", JSON.stringify(sepet));}constfiyatCubugu= document.querySelector(".price-filter");fiyatCubugu.addEventListener("input", () => {document.querySelector(".price-value").textContent = fiyatCubugu.value;constfiltrelenmis= urunDeposu.filter(u => (u.fields.price /100) <= fiyatCubugu.value);magazayiOlustur(filtrelenmis);});window.addEventListener("DOMContentLoaded", () => {sepet = localStorage.getItem("comfySepet") ? JSON.parse(localStorage.getItem("comfySepet")) : [];urunleriUzaktenCek();sepetiGuncelle();});
Harika bir fikir! Geliştirdiğin tüm bu projeleri tek bir merkezden yönetebileceğin, modern, karanlık mod (dark mode) destekli ve kart tasarımlı bir Geliştirici Portfolyo Paneli (Dashboard) hazırladım.
Bu arayüz sayesinde kullanıcılar projelerini kategorilerine göre filtreleyebilecek, canlı arama yapabilecek ve her projenin üzerine gelindiğinde pürüzsüz animasyonlar görecek.
İşte projenin birbiriyle tam uyumlu HTML, CSS ve JavaScript kodları:
<!DOCTYPE html><htmllang="tr"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Proje Portfolyo Paneli</title><linkrel="stylesheet"href="style.css"></head><body><!-- Yan Menü (Sidebar) --><asideclass="sidebar"><divclass="logo-area"><divclass="logo-icon">JS</div><h2>JS DevPanel</h2></div><navclass="nav-menu"><buttonclass="nav-item active"data-filter="hepsi">🚀 Tüm Projeler</button><buttonclass="nav-item"data-filter="temel">🎨 Temel DOM</button><buttonclass="nav-item"data-filter="oop">🧱 Nesne Yönelimli</button><buttonclass="nav-item"data-filter="modern">⚡ Modern ES6+</button><buttonclass="nav-item"data-filter="api">📡 API & Asenkron</button></nav><divclass="sidebar-footer"><p>©2026Portfolyo Paneli</p></div></aside><!-- Ana İçerik Alanı --><mainclass="main-content"><!-- Üst Bar (Header) --><headerclass="top-bar"><divclass="search-box"><inputtype="text"id="search-input"placeholder="Projelerde ara (Örn: Sayaç, Sepet)..."></div><divclass="stats-mini"><span>Toplam Proje: <strongid="total-count">0</strong></span></div></header><!-- Proje Kartları Izgarası (Grid) --><sectionclass="dashboard-grid"id="projects-grid"><!-- Kartlar JavaScript tarafından buraya dinamik olarak eklenecek --></section></main><scriptsrc="app.js"></script></body></html>
/* Temel Değişkenler ve Renk Paleti */:root {--bg-main: #0f172a;--bg-sidebar: #1e293b;--bg-card: #334155;--text-main: #f8fafc;--text-muted: #94a3b8;--accent: #6366f1;--accent-hover: #4f46e5;--success: #10b981;}* {margin:0;padding:0;box-sizing: border-box;}body {font-family:'Segoe UI', system-ui, sans-serif;background-color: var(--bg-main);color: var(--text-main);display: flex;min-height:100vh;overflow-x: hidden;}/* Yan Menü (Sidebar) Tasarımı */.sidebar {width:260px;background-color: var(--bg-sidebar);padding:2rem1.5rem;display: flex;flex-direction: column;border-right:1pxsolid rgba(255,255,255,0.05);}.logo-area {display: flex;align-items: center;gap:0.75rem;margin-bottom:3rem;}.logo-icon {background: var(--accent);color: white;font-weight: bold;padding:0.5rem;border-radius:8px;font-size:1.2rem;}.logo-area h2 {font-size:1.3rem;letter-spacing:0.5px;}.nav-menu {display: flex;flex-direction: column;gap:0.5rem;}.nav-item {background: transparent;border: none;color: var(--text-muted);padding:0.75rem1rem;text-align: left;font-size:1rem;font-weight:500;cursor: pointer;border-radius:10px;transition: all0.2sease;}.nav-item:hover, .nav-item.active {background-color: var(--accent);color: white;}.sidebar-footer {margin-top: auto;font-size:0.8rem;color: var(--text-muted);text-align: center;}/* Ana İçerik Bölümü */.main-content {flex:1;padding:2rem;display: flex;flex-direction: column;gap:2rem;}/* Üst Bar Tasarımı */.top-bar {display: flex;justify-content: space-between;align-items: center;background: var(--bg-sidebar);padding:1rem1.5rem;border-radius:16px;box-shadow:04px6px-1pxrgba(0,0,0,0.1);}.search-box input {width:350px;padding:0.75rem1.2rem;background: var(--bg-main);border:1pxsolid rgba(255,255,255,0.1);border-radius:12px;color: white;font-size:0.95rem;transition: all0.2s;}.search-box input:focus {outline: none;border-color: var(--accent);box-shadow:0003pxrgba(99,102,241,0.2);}.stats-mini {font-size:1rem;color: var(--text-muted);}.stats-mini strong {color: var(--success);}/* Proje Kartları Izgarası (Grid) */.dashboard-grid {display: grid;grid-template-columns: repeat(auto-fill, minmax(280px,1fr));gap:1.5rem;}/* Kart Tasarımı ve Animasyonlar */.project-card {background: var(--bg-sidebar);border-radius:16px;padding:1.5rem;border:1pxsolid rgba(255,255,255,0.02);display: flex;flex-direction: column;gap:1rem;transition: all0.3scubic-bezier(0.4,0,0.2,1);}.project-card:hover {transform: translateY(-5px);box-shadow:020px25px-5pxrgba(0,0,0,0.3);border-color: rgba(99,102,241,0.3);}.card-tag {align-self: flex-start;padding:0.25rem0.6rem;border-radius:6px;font-size:0.75rem;font-weight:600;text-transform: uppercase;background: rgba(99,102,241,0.15);color: #a5b4fc;}.project-card h3 {font-size:1.2rem;}.project-card p {font-size:0.9rem;color: var(--text-muted);line-height:1.5;flex:1;/* Butonları alta sabitlemek için esnetir */}.launch-btn {background: var(--accent);color: white;text-decoration: none;padding:0.6rem1rem;border-radius:10px;text-align: center;font-size:0.9rem;font-weight:600;transition: background0.2s;}.launch-btn:hover {background: var(--accent-hover);}
// 1. Panelde sergilenecek proje verilerimizconstprojeler= [{id:1,baslik:"Color Flipper",kategori:"temel",aciklama:"Rastgele HEX kodları üreten ve arka planı cam efekti kartıyla değiştiren uygulama.",link:"01-color-flipper/index.html"},{id:2,baslik:"Gelişmiş Sayaç",kategori:"temel",aciklama:"Neumorphic tasarımlı, sayı durumuna göre renk değiştiren akıllı sayaç.",link:"02-counter/index.html"},{id:3,baslik:"Müşteri Yorumları",kategori:"temel",aciklama:"Dizi verileri arasında ileri-geri butonlarıyla gezinen profil kartı.",link:"03-reviews/index.html"},{id:4,baslik:"Akordeon SSS",kategori:"temel",aciklama:"Tıklandığında açılan ve diğerlerini otomatik kapatan soru-cevap kartları.",link:"06-questions/index.html"},{id:5,baslik:"Restoran Menüsü",kategori:"temel",aciklama:"Yemek listesini kategorilere göre anlık süzen dinamik grid yapısı.",link:"07-menu/index.html"},{id:6,baslik:"Grocery Bud",kategori:"temel",aciklama:"Local Storage destekli, eleman ekleme, silme ve düzenleme yapabilen sepet.",link:"13-grocery-bud/index.html"},{id:7,baslik:"OOP Sayaç",kategori:"oop",aciklama:"JavaScript Class yapısı ile üretilmiş, sayfada çoklu çalışan bağımsız sayaçlar.",link:"15-oop-counter/index.html"},{id:8,baslik:"OOP Galeri",kategori:"oop",aciklama:"Masonry ızgara sistemli ve tıklandığında açılan koyu temalı Lightbox galeri.",link:"16-oop-gallery/index.html"},{id:9,baslik:"Dashboard Sayaçları",kategori:"modern",aciklama:"Açılışta sıfırdan hedefe doğru hızla sayan parlayan neon efektli sayılar.",link:"17-numbers/index.html"},{id:10,baslik:"Dad Jokes API",kategori:"api",aciklama:"Uzak sunucudan asenkron veri çekerek sohbet balonu içine basan espri motoru.",link:"20-dad-jokes/index.html"},{id:11,baslik:"GitHub Pagination",kategori:"api",aciklama:"Gelen büyük verileri sayfa başına 10'arlı gruplara bölen sayfalama sistemi.",link:"24-pagination/index.html"},{id:12,baslik:"Comfy Mağazası",kategori:"api",aciklama:"Sağdan kayan sepet çekmeceli, fiyat çubuklu ve çoklu filtreli dev e-ticaret sistemi.",link:"25-comfy-store/index.html"}];// 2. DOM Elemanlarını Seçelimconstgrid= document.getElementById("projects-grid");constaramaInput= document.getElementById("search-input");constfiltreButonlari= document.querySelectorAll(".nav-item");consttoplamSayiYazisi= document.getElementById("total-count");// 3. Projeleri Ekrana Basan FonksiyonfunctionprojeleriGoster(liste) {if(liste.length ===0) {grid.innerHTML =`<h3 style="grid-column: 1/-1; text-align: center; color: var(--text-muted);">Aradığınız kriterde proje bulunamadı.</h3>`;toplamSayiYazisi.textContent =0;return;}constkartlarHtml= liste.map(proje => {return`<article class="project-card" data-category="${proje.kategori}"><span class="card-tag">${proje.kategori}</span><h3>${proje.baslik}</h3><p>${proje.aciklama}</p><a href="${proje.link}" target="_blank" class="launch-btn">Projeyi Başlat 🚀</a></article>`;}).join("");grid.innerHTML = kartlarHtml;toplamSayiYazisi.textContent = liste.length;}// 4. Kategori Filtreleme MekanizmasıfiltreButonlari.forEach(buton => {buton.addEventListener("click", (e) => {// Aktif buton görsel sınıfını değiştirelimfiltreButonlari.forEach(b => b.classList.remove("active"));e.currentTarget.classList.add("active");constkategoriIsmi= e.currentTarget.dataset.filter;// Input alanını temizleyelim ki filtre çakışmasınaramaInput.value ="";if(kategoriIsmi ==="hepsi") {projeleriGoster(projeler);}else{constfiltrelenmis= projeler.filter(p => p.kategori === kategoriIsmi);projeleriGoster(filtrelenmis);}});});// 5. Canlı Arama Mekanizması (Harf Yazıldıkça Çalışır)aramaInput.addEventListener("keyup", () => {constarananKelime= aramaInput.value.toLowerCase();// Sol menüdeki aktifliği "Tüm Projeler"e çekelim ki genel arama yapsınfiltreButonlari.forEach(b => b.classList.remove("active"));filtreButonlari[0].classList.add("active");constaramaSonuclari= projeler.filter(p => {returnp.baslik.toLowerCase().includes(arananKelime) ||p.aciklama.toLowerCase().includes(arananKelime);});projeleriGoster(aramaSonuclari);});// 6. Sayfa İlk Açıldığında Tüm Projeleri Listelewindow.addEventListener("DOMContentLoaded", () => {projeleriGoster(projeler);});
Klasör yapını şu şekilde
kurgularsan paneldeki Projeyi
Başlat
butonları hedef projeleri tarayıcıda yeni sekmede kusursuzca
açacaktır:
📂 JavaScript-Portfolyom/├── 📄 index.html (Yukarıdaki dashboard dosyası)├── 📄 style.css (Yukarıdaki dashboard dosyası)├── 📄 app.js (Yukarıdaki dashboard dosyası)│├── 📂 01-color-flipper/│ └── 📄 index.html, style.css, app.js├── 📂 02-counter/│ └── 📄 index.html, style.css, app.js└── 📂 25-comfy-store/└── 📄 index.html, style.css, app.js