Değişkenler ve Veri Tipleri
Giriş — Verinin Gücü
Her program, özünde veriyi işler. Bir e-ticaret sitesi ürün fiyatlarını, bir sosyal medya uygulaması kullanıcı bilgilerini, bir hava durumu uygulaması sıcaklık değerlerini işler. Ama bu verilerin bir yerde saklanması gerekir — tıpkı bir mutfakta malzemelerin kavanozlarda, dolaplarda, buzdolabında saklanması gibi.
İşte değişkenler (variables), programlamadaki o kavanozlardır. Veriye bir isim verirsiniz, onu bir kutunun içine koyarsınız ve daha sonra o isimle tekrar erişirsiniz. Bu kadar basit görünse de, JavaScript'te değişken tanımlamanın üç farklı yolu vardır ve her birinin davranışı farklıdır. Ayrıca JavaScript'in yedi farklı ilkel (primitive) veri tipi vardır — bunların ne olduğunu, nasıl davrandığını ve birbirlerinden nasıl ayırt edileceğini bu derste öğreneceksiniz.
Analoji: Değişkenleri etiketli kutular olarak düşünün. Kutunun üzerindeki etiket değişkenin adı, kutunun içindeki şey değişkenin değeridir.
let yas = 25dediğinizde, "yas" etiketli bir kutu oluşturup içine 25 sayısını koyarsınız. Daha sonrayasetiketini kullanarak kutunun içindeki değere ulaşırsınız.
Değişken Tanımlama — var, let, const
JavaScript'te değişken tanımlamanın üç yolu vardır: var, let ve const. Bu üçünün tarihsel gelişimini ve farkları anlamak, JavaScript'i doğru yazmak için kritik öneme sahiptir.
var — Eski Usul (ES5 ve Öncesi)
JavaScript'in 1995'ten 2015'e kadar tek değişken tanımlama yolu var idi. Ama var'ın bazı davranışları, geliştiricilerin başını ağrıtıyordu:
// var ile temel kullanım
var isim = "Ahmet";
var yas = 30;
console.log(isim); // "Ahmet"
// var tekrar tanımlamaya izin verir — tehlikeli!
var isim = "Mehmet"; // Hata vermez, sessizce üzerine yazar
console.log(isim); // "Mehmet"var'ın sorunlu davranışları:
1. Function scope (Fonksiyon kapsamlı):
// var, block scope'a sahip DEĞİLDİR
if (true) {
var mesaj = "Merhaba";
}
console.log(mesaj); // "Merhaba" — if bloğunun dışında erişilebilir!
// Döngüde de aynı sorun
for (var i = 0; i < 3; i++) {
// bir şeyler yap
}
console.log(i); // 3 — döngü dışında erişilebilir!2. Hoisting (Yukarı çekme):
// var tanımlamaları dosyanın başına "çekilir"
console.log(x); // undefined — hata vermez!
var x = 5;
// JavaScript bunu şöyle yorumlar:
// var x; ← tanımlama yukarı çekildi
// console.log(x); ← undefined
// x = 5; ← atama yerinde kaldıBu davranışlar, özellikle büyük projelerde hatalara yol açıyordu. var ile bir değişkeni yanlışlıkla iki kez tanımlayabilir, beklenmedik scope sorunları yaşayabilirsiniz. İşte bu yüzden ES6 ile let ve const geldi.
⚠️ Dikkat: Modern JavaScript'te var kullanmayın. Bu kursta var'ı öğretiyoruz çünkü eski kodlarda karşınıza çıkacak — ama yeni kod yazarken her zaman let veya const kullanın.
let — Modern Değişken (ES6+)
let, var'ın sorunlarını çözmek için tasarlandı:
// let ile temel kullanım
let sehir = "İstanbul";
sehir = "Ankara"; // Değer değiştirilebilir
console.log(sehir); // "Ankara"
// let tekrar tanımlamaya İZİN VERMEZ
let sehir = "İzmir"; // ❌ SyntaxError: Identifier 'sehir' has already been declaredBlock scope (Blok kapsamlı):
// let, block scope'a sahiptir — if, for, while blokları
if (true) {
let mesaj = "Merhaba";
console.log(mesaj); // "Merhaba" — blok içinde erişilebilir
}
console.log(mesaj); // ❌ ReferenceError: mesaj is not defined
// Döngüde de güvenli
for (let i = 0; i < 3; i++) {
console.log(i); // 0, 1, 2
}
console.log(i); // ❌ ReferenceError: i is not defined — mükemmel!Temporal Dead Zone (TDZ):
// let hoisting yapar AMA erişime izin vermez (TDZ)
console.log(x); // ❌ ReferenceError: Cannot access 'x' before initialization
let x = 5;
// Bu aslında iyi bir şey — hatayı erken yakalarvar'da undefined alıp devam ediyordunuz ama nerede hata olduğunu bulmak zorlaşıyordu. let ile JavaScript hemen hata fırlatır ve sorunu anında görürsünüz.
const — Sabit Değer (ES6+)
const, bir kez atandıktan sonra yeniden atanamayan değişkenler için kullanılır:
// const ile temel kullanım
const PI = 3.14159;
const MAX_KULLANICI = 100;
const SITE_ADI = "JavaScript Kursu";
PI = 3.14; // ❌ TypeError: Assignment to constant variable
// const da block scope'a sahiptir
if (true) {
const gecici = "Bu blokta kalır";
}
console.log(gecici); // ❌ ReferenceErrorÖnemli nüans — `const` nesneleri:
// const, DEĞİŞKENİN YENİDEN ATANAMAYACAĞI anlamına gelir
// İçeriğin değiştirilemeyeceği anlamına GELMEZ!
const kullanici = { isim: "Ali", yas: 25 };
kullanici.yas = 26; // ✅ Bu çalışır! İçeriği değiştirebilirsiniz
console.log(kullanici); // { isim: "Ali", yas: 26 }
kullanici = {}; // ❌ TypeError — yeniden atama yapılamaz
const sayilar = [1, 2, 3];
sayilar.push(4); // ✅ Çalışır! Diziye eleman ekleyebilirsiniz
console.log(sayilar); // [1, 2, 3, 4]
sayilar = [5, 6, 7]; // ❌ TypeError — yeniden atama yapılamazAnaloji:
constbir evi adres defterinize yazmak gibidir. Adres (referans) değişmez — hep aynı eve gidersiniz. Ama evin içinde tadilat yapabilirsiniz (nesne özelliklerini değiştirebilirsiniz).constadresin değişmesini engeller, evin içini değil.
var vs let vs const — Karşılaştırma Tablosu
| Özellik | var | let | const |
|---|---|---|---|
| Scope | Function | Block | Block |
| Tekrar tanımlama | ✅ İzin verir | ❌ Hata | ❌ Hata |
| Yeniden atama | ✅ Evet | ✅ Evet | ❌ Hayır |
| Hoisting | Tanımlanır (undefined) | TDZ (hata verir) | TDZ (hata verir) |
Global scope'ta window'a eklenir | ✅ Evet | ❌ Hayır | ❌ Hayır |
Hangi Durumda Hangisini Kullanmalı?
// KURAL: Varsayılan olarak const kullan
const API_URL = "https://api.example.com";
const kullaniciListesi = [];
// Değer DEĞİŞECEKSE let kullan
let sayac = 0;
let toplamPuan = 0;
let aktifMi = true;
// var KULLANMA — hiçbir zaman
// var eskiAliskanlik = "kötü"; // ❌💡 İpucu: "Her şeyi const ile başlat, değiştirmen gerekirse let'e çevir" kuralı en güvenli yaklaşımdır. Profesyonel JavaScript projelerinde kodun %80-90'ı const ile yazılır. Bu, kodun okunabilirliğini artırır — const gördüğünüzde "bu değer değişmeyecek, güvende" diye düşünebilirsiniz.
Değişken İsimlendirme Kuralları
İyi isimlendirme, iyi kodun temelidir. Bir değişken adı, o değişkenin ne olduğunu anlatmalıdır — koda bakan biri, değişkenin ne işe yaradığını ismine bakarak anlayabilmelidir.
Zorunlu Kurallar (Bozarsan Hata Alırsın)
// ✅ İzin Verilen
let isim = "Ali";
let _ozel = "alt çizgi ile başlayabilir";
let $dolar = "dolar işareti ile başlayabilir";
let isim2 = "rakam içerebilir (baştaki hariç)";
let çokUzunBirDeğişkenAdıKullanabilirsiniz = true; // Unicode desteklenir
// ❌ Hata Verenler
let 2isim = "Ali"; // Rakamla başlayamaz
let benim-isim = "Ali"; // Tire (-) kullanılamaz
let let = "değer"; // Ayrılmış kelimeler (reserved words) kullanılamaz
let class = "değer"; // class da ayrılmış kelimedirAyrılmış Kelimeler (Reserved Words)
Bu kelimeleri değişken adı olarak kullanamazsınız:
break, case, catch, class, const, continue, debugger, default,
delete, do, else, export, extends, finally, for, function, if,
import, in, instanceof, let, new, return, super, switch, this,
throw, try, typeof, var, void, while, with, yieldİsimlendirme Konvansiyonları (Zorunlu Değil Ama Uyulması Gereken)
// camelCase — JavaScript'te standart (değişkenler ve fonksiyonlar)
let kullaniciAdi = "ali_yilmaz";
let toplamSiparisSayisi = 42;
let aktifMi = true;
// PascalCase — Class isimleri için
class KullaniciBilgisi { }
class SiparisYonetici { }
// SCREAMING_SNAKE_CASE — Sabitler için (gerçek sabitler)
const MAX_DENEME_SAYISI = 3;
const API_BASE_URL = "https://api.example.com";
const SANIYEDE_MILISANIYE = 1000;
// _ prefix — "özel" (private) değişkenler için (konvansiyon)
let _dahiliSayac = 0;İyi vs Kötü İsimlendirme
// ❌ KÖTÜ — ne olduğu belli değil
let x = 5;
let d = new Date();
let arr = [1, 2, 3];
let flag = true;
let temp = "ali@email.com";
// ✅ İYİ — kendini açıklayan isimler
let kullaniciYasi = 5;
let kayitTarihi = new Date();
let sinifPuanlari = [1, 2, 3];
let emailDogrulandi = true;
let kullaniciEmail = "ali@email.com";
// ❌ KÖTÜ — çok genel
let veri = fetchUser();
let sonuc = hesapla();
// ✅ İYİ — spesifik
let kullaniciBilgisi = fetchUser();
let vergiMiktari = hesaplaVergi();⚠️ Dikkat: Boolean değişkenler is, has, can, should gibi ön eklerle başlamalıdır. Bu, değişkenin bir evet/hayır sorusunu cevapladığını anında belli eder:
let isActive = true; // Aktif mi?
let hasPermission = false; // İzni var mı?
let canEdit = true; // Düzenleyebilir mi?
let shouldRedirect = false; // Yönlendirmeli mi?Primitive (İlkel) Veri Tipleri
JavaScript'te 7 ilkel (primitive) veri tipi vardır. "İlkel" demek, bu değerlerin en temel yapı taşları olduğu anlamına gelir — daha küçük parçalara bölünemezler ve değiştirilemezler (immutable).
1. String — Metin
String, karakter dizisidir. Tek tırnak, çift tırnak veya backtick ile oluşturulur:
// Üç farklı yol — hepsi aynı sonucu verir
let isim1 = 'Ali'; // tek tırnak
let isim2 = "Ali"; // çift tırnak
let isim3 = `Ali`; // backtick (template literal) — ES6
// Tek ve çift tırnak arasında fark yoktur
// Ama iç içe kullanırken dikkatli olun:
let mesaj1 = 'O "harika" dedi'; // İçinde çift tırnak varsa dışı tek
let mesaj2 = "It's a beautiful day"; // İçinde tek tırnak varsa dışı çift
let mesaj3 = 'It\'s escaped'; // Escape karakteri ile
// Template literal (backtick) — EN KULLANIŞLI
let ad = "Ayşe";
let yas = 28;
let tanitim = `Merhaba, ben ${ad} ve ${yas} yaşındayım.`;
console.log(tanitim); // "Merhaba, ben Ayşe ve 28 yaşındayım."
// Template literal içinde ifade (expression) kullanabilirsiniz
console.log(`2 + 3 = ${2 + 3}`); // "2 + 3 = 5"
console.log(`Büyük harf: ${ad.toUpperCase()}`); // "Büyük harf: AYŞE"
// Çok satırlı string — sadece backtick ile mümkün
let adres = `Atatürk Caddesi
No: 42, Kat: 3
İstanbul, Türkiye`;
console.log(adres);
// Atatürk Caddesi
// No: 42, Kat: 3
// İstanbul, TürkiyeString immutable'dır (değiştirilemez):
let kelime = "merhaba";
kelime[0] = "M"; // Bu çalışmaz — sessizce görmezden gelinir
console.log(kelime); // "merhaba" — değişmedi!
// Yeni bir string oluşturmalısınız
kelime = "M" + kelime.slice(1); // "Merhaba"2. Number — Sayı
JavaScript'te tam sayı ve ondalık sayı ayrımı yoktur — ikisi de number tipindedir:
let tamSayi = 42;
let ondalik = 3.14;
let negatif = -273.15;
let bilimsel = 2.998e8; // 2.998 × 10^8 = 299800000 (ışık hızı m/s)
// Hepsi number tipindedir
console.log(typeof tamSayi); // "number"
console.log(typeof ondalik); // "number"Özel sayı değerleri:
let sonsuz = Infinity; // Sonsuz
let negatifSonsuz = -Infinity;
let sayi_degil = NaN; // Not a Number
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log("abc" * 2); // NaN — sayı olmayan çarpım
// NaN'ın garip davranışı
console.log(NaN === NaN); // false! — NaN kendisine bile eşit değil!
console.log(isNaN(NaN)); // true
console.log(Number.isNaN(NaN)); // true — daha güvenilir versiyonKayan nokta (floating point) hassasiyet sorunu:
console.log(0.1 + 0.2); // 0.30000000000000004 — BEKLENMEDIK!
console.log(0.1 + 0.2 === 0.3); // false!
// Neden? JavaScript IEEE 754 standardını kullanır.
// Bazı ondalık sayılar ikili (binary) sistemde tam temsil edilemez.
// Çözüm 1: toFixed ile yuvarlama
console.log((0.1 + 0.2).toFixed(2)); // "0.30" (string döner!)
console.log(Number((0.1 + 0.2).toFixed(2))); // 0.3 (number)
// Çözüm 2: Küçük fark kontrolü (epsilon)
function esitMi(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
console.log(esitMi(0.1 + 0.2, 0.3)); // true
// Çözüm 3: Tam sayılarla çalış (kuruş cinsinden)
let fiyat = 1999; // 19.99 TL → kuruş olarak sakla
console.log(`Fiyat: ${(fiyat / 100).toFixed(2)} TL`); // "Fiyat: 19.99 TL"⚠️ Dikkat: Para hesaplamalarında asla ondalık sayıları doğrudan kullanmayın. Her zaman en küçük birim (kuruş, cent) cinsinden tam sayı olarak saklayın. Banka ve finans uygulamalarında bu bir kuraldır. 0.1 + 0.2 !== 0.3 hatası, gerçek projelerde para kaybına yol açabilir.
Number sınırları:
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991 (2^53 - 1)
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
// Bu sınırı aşarsanız hesaplamalar hatalı olur
console.log(9007199254740991 + 1); // 9007199254740992 ✅
console.log(9007199254740991 + 2); // 9007199254740992 ❌ Yanlış!3. BigInt — Büyük Tam Sayılar (ES2020)
Number.MAX_SAFE_INTEGER'dan büyük tam sayılar için BigInt kullanılır:
// Sonuna n ekleyerek oluşturulur
const buyukSayi = 9007199254740993n;
const digerBuyuk = BigInt("9007199254740993");
console.log(buyukSayi + 1n); // 9007199254740994n — doğru!
// BigInt ve Number karıştırılamaz
console.log(buyukSayi + 1); // ❌ TypeError: Cannot mix BigInt and other types
console.log(buyukSayi + BigInt(1)); // ✅ 9007199254740994n4. Boolean — Mantıksal Değer
Sadece iki değeri vardır: true veya false. Karar mekanizmalarının temel yapı taşıdır:
let aktifMi = true;
let silindi = false;
// Karşılaştırma sonuçları boolean döner
console.log(5 > 3); // true
console.log(10 === 20); // false
console.log("abc" === "abc"); // true
// Boolean fonksiyonlar
let yas = 17;
let yetiskinMi = yas >= 18;
console.log(yetiskinMi); // false5. undefined — Tanımsız
Bir değişken tanımlanmış ama değer atanmamışsa, değeri undefined'dır:
let isim;
console.log(isim); // undefined
console.log(typeof isim); // "undefined"
// Bir fonksiyon değer döndürmezse
function selamla() {
console.log("Merhaba");
// return yok
}
let sonuc = selamla();
console.log(sonuc); // undefined
// Bir nesnenin olmayan özelliği
let kullanici = { isim: "Ali" };
console.log(kullanici.yas); // undefined — yas özelliği yok6. null — Bilinçli Boşluk
null, bir değişkenin bilerek boş bırakıldığını ifade eder:
let seciliKullanici = null; // Henüz kimse seçilmedi
// Bir fonksiyondan sonuç bulunamazsa
function kullaniciBul(id) {
// Veritabanında aradık, bulamadık
return null; // "Sonuç yok" anlamında
}
let kullanici = kullaniciBul(999);
if (kullanici === null) {
console.log("Kullanıcı bulunamadı");
}`undefined` vs `null` — Fark nedir?
// undefined → "Değer hiç atanmadı, sistem tarafından verilen varsayılan"
// null → "Bilerek 'boş' olarak atandı, geliştirici tarafından belirlenmiş"
let a; // undefined — henüz değer yok
let b = null; // null — bilinçli olarak boş
// İkisinin tipi
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" — BU BİR BUG! 1995'ten beri var.
// Eşitlik karşılaştırması
console.log(null == undefined); // true — gevşek eşitlik
console.log(null === undefined); // false — sıkı eşitlikAnaloji: Bir form düşünün. "Telefon" alanı
undefinedise, form o alanı hiç içermemiş demektir (alan yok).nullise, alan var ama kullanıcı bilerek boş bırakmış demektir (alan var, değer yok).
7. Symbol — Benzersiz Tanımlayıcı (ES6)
Symbol, her çağrıldığında tamamen benzersiz bir değer üretir. Genellikle nesne özelliklerinde çakışmayı önlemek için kullanılır:
const id1 = Symbol("kullanici");
const id2 = Symbol("kullanici");
console.log(id1 === id2); // false — aynı açıklamaya sahip olsalar bile benzersiz!
console.log(typeof id1); // "symbol"
// Pratik kullanım — nesne özelliklerinde çakışma önleme
const GİZLİ_ANAHTAR = Symbol("gizli");
let kullanici = {
isim: "Ali",
[GİZLİ_ANAHTAR]: "çok-gizli-değer"
};
console.log(kullanici.isim); // "Ali"
console.log(kullanici[GİZLİ_ANAHTAR]); // "çok-gizli-değer"
// Symbol özellikler normal iterasyonda görünmez
console.log(Object.keys(kullanici)); // ["isim"] — Symbol yok!Symbol ileri seviye bir konudur. Şimdilik var olduğunu bilmeniz yeterli — ilerleyen bölümlerde Iterator ve Generator konusunda tekrar karşılaşacağız.
typeof Operatörü — Tipi Sorgulama
typeof operatörü, bir değerin tipini string olarak döndürür:
console.log(typeof "merhaba"); // "string"
console.log(typeof 42); // "number"
console.log(typeof 3.14); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" ← BUG! (ama düzeltilemez)
console.log(typeof Symbol()); // "symbol"
console.log(typeof 42n); // "bigint"
// Referans tipleri
console.log(typeof {}); // "object"
console.log(typeof []); // "object" ← Dizi de object!
console.log(typeof function(){}); // "function"typeof'un tuzakları:
// 1. null sorunu — typeof null === "object"
// Bu 1995'ten kalma bir bug. Düzeltmek geriye uyumluluğu bozacağı için düzeltilmedi.
let deger = null;
console.log(typeof deger); // "object" — AMA null bir object DEĞİL!
// null kontrolü için typeof kullanmayın, doğrudan karşılaştırın:
if (deger === null) {
console.log("Değer null");
}
// 2. Dizi kontrolü — typeof [] === "object"
let liste = [1, 2, 3];
console.log(typeof liste); // "object" — Dizi mi nesne mi?
// Dizi kontrolü için Array.isArray() kullanın:
console.log(Array.isArray(liste)); // true
console.log(Array.isArray({})); // false💡 İpucu: typeof çoğu durumda işe yarasa da, null ve diziler için yanıltıcıdır. Profesyonel kodda tip kontrolü için genellikle daha güvenilir yöntemler kullanılır. TypeScript ise bu sorunları kökünden çözer — ilerde göreceğiz.
Primitive vs Reference — Değer ve Referans Farkı
Bu, JavaScript'teki en kritik kavramlardan biridir. Primitive tipler ve referans tipler (object, array, function) bellekte farklı şekilde saklanır ve bu fark, birçok hatanın kaynağıdır.
Primitive Tipler — Değer Kopyalanır
let a = 10;
let b = a; // a'nın DEĞERİ kopyalanır (10)
b = 20; // b'yi değiştirmek a'yı ETKİLEMEZ
console.log(a); // 10 — değişmedi!
console.log(b); // 20Analoji: Bir kağıda telefon numaranızı yazıp fotokopi çektiğinizi düşünün. Fotokopideki numarayı silip başka bir şey yazsanız, orijinal kağıttaki numara değişmez. Primitive değerler böyle çalışır.
Referans Tipler — Adres Kopyalanır
let orijinal = { isim: "Ali", yas: 25 };
let kopya = orijinal; // Değer değil, ADRES (referans) kopyalanır!
kopya.yas = 30; // kopya üzerinden değiştirdiğimiz şey...
console.log(orijinal.yas); // 30 — ...orijinali de değiştirir!
console.log(kopya.yas); // 30Analoji: İki anahtar düşünün, ama ikisi de aynı evin kapısını açıyor. Birinci anahtarla girip mobilyaları değiştirirseniz, ikinci anahtarla girdiğinizde de değişmiş mobilyaları görürsünüz. Çünkü iki anahtar (değişken) aynı eve (nesneye) işaret ediyor.
// Gerçek kopya oluşturmak için spread operator veya Object.assign kullanın
let orijinal2 = { isim: "Ayşe", yas: 28 };
let gercekKopya = { ...orijinal2 }; // spread ile yüzeysel kopya
gercekKopya.yas = 35;
console.log(orijinal2.yas); // 28 — orijinal değişmedi!
console.log(gercekKopya.yas); // 35Bu konuyu Bölüm 3'te (Nesneler) çok daha detaylı işleyeceğiz. Şimdilik primitive ve referans arasındaki temel farkı bilmeniz yeterli.
Tip Dönüşümleri (Type Conversion)
JavaScript dinamik tipli bir dil olduğu için, bir veri tipini başka bir tipe dönüştürmeniz gerekebilir. İki tür dönüşüm vardır: açık (explicit) ve örtük (implicit/coercion).
Açık Dönüşüm (Explicit Conversion)
Siz bilinçli olarak dönüştürürsünüz:
// String'e dönüştürme
let sayi = 42;
let metin = String(sayi); // "42"
let metin2 = sayi.toString(); // "42"
let metin3 = sayi + ""; // "42" — ama bu implicit'e yakın
console.log(typeof metin); // "string"
// Number'a dönüştürme
let str = "123";
let num = Number(str); // 123
let num2 = parseInt(str); // 123 (tam sayı)
let num3 = parseFloat("3.14"); // 3.14 (ondalık)
let num4 = +"42"; // 42 — unary plus operatörü
console.log(Number("abc")); // NaN — dönüştürülemez
console.log(Number("")); // 0
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
// parseInt'in ikinci parametresi — taban (radix)
console.log(parseInt("0xFF", 16)); // 255 (hexadecimal)
console.log(parseInt("111", 2)); // 7 (binary)
console.log(parseInt("10px")); // 10 — sayı olmayan kısmı atar
console.log(parseInt("px10")); // NaN — sayı ile başlamıyorsa
// Boolean'a dönüştürme
console.log(Boolean(1)); // true
console.log(Boolean(0)); // false
console.log(Boolean("merhaba")); // true
console.log(Boolean("")); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // falseÖrtük Dönüşüm (Type Coercion)
JavaScript, operatörler kullanıldığında otomatik tip dönüşümü yapar. Bu bazen kullanışlıdır, bazen de çok şaşırtıcı sonuçlar verir:
// String birleştirme — + operatörü string ile kullanılırsa
console.log("5" + 3); // "53" — number string'e dönüştürüldü!
console.log("5" + true); // "5true"
console.log("5" + null); // "5null"
// Ama diğer operatörler string'i number'a dönüştürür!
console.log("5" - 3); // 2 — string number'a dönüştürüldü
console.log("5" * 3); // 15
console.log("5" / 2); // 2.5
console.log("5" - true); // 4 (true → 1)Bu davranışlar JavaScript'in en çok eleştirilen yanlarından biridir. Bir sonraki derste (Operatörler) coercion tuzaklarını ve nasıl kaçınacağınızı çok daha detaylı işleyeceğiz.
Gerçek Dünya Örneği: Kullanıcı Profil Kartı
Öğrendiğimiz kavramları birleştiren bir örnek yapalım:
// Kullanıcı profil kartı oluşturucu
const VARSAYILAN_AVATAR = "https://example.com/default-avatar.png";
const MAX_BIO_UZUNLUK = 150;
// Kullanıcı bilgileri
let kullaniciAdi = "tolgahan_dev";
let tamIsim = "Tolgahan Yılmaz";
let yas = 28;
let bio = "Full-stack developer. JavaScript ve TypeScript tutkunu. Açık kaynak destekçisi.";
let takipciSayisi = 1250;
let premium = true;
let avatarUrl = null; // Henüz avatar yüklememiş
// Avatar kontrolü — null ise varsayılanı kullan
let gosterilecekAvatar = avatarUrl !== null ? avatarUrl : VARSAYILAN_AVATAR;
// Bio kısaltma
let kisaBio = bio.length > MAX_BIO_UZUNLUK
? bio.slice(0, MAX_BIO_UZUNLUK) + "..."
: bio;
// Takipçi sayısını formatla
function takipciFormatla(sayi) {
if (typeof sayi !== "number" || isNaN(sayi)) {
return "0";
}
if (sayi >= 1000000) {
return (sayi / 1000000).toFixed(1) + "M";
}
if (sayi >= 1000) {
return (sayi / 1000).toFixed(1) + "K";
}
return String(sayi);
}
// Profil kartını oluştur
let profilKarti = `
╔══════════════════════════════════╗
║ ${premium ? "⭐" : " "} @${kullaniciAdi}
║ ${tamIsim} (${yas})
║ ${kisaBio}
║ 👥 ${takipciFormatla(takipciSayisi)} takipçi
║ 📷 ${gosterilecekAvatar === VARSAYILAN_AVATAR ? "Varsayılan avatar" : "Özel avatar"}
╚══════════════════════════════════╝
`;
console.log(profilKarti);
// Tip kontrolü
console.log("--- Tip Kontrolleri ---");
console.log(`kullaniciAdi: ${typeof kullaniciAdi}`); // string
console.log(`yas: ${typeof yas}`); // number
console.log(`premium: ${typeof premium}`); // boolean
console.log(`avatarUrl: ${typeof avatarUrl}`); // object (null bug'ı!)
console.log(`avatarUrl === null: ${avatarUrl === null}`); // trueBu örnek, tek bir senaryoda const, let, string, number, boolean, null, typeof, template literal ve koşullu ifadeleri bir arada gösteriyor. Her bir kavramın gerçek dünyada nasıl kullanıldığını somut olarak görebilirsiniz.
Yaygın Hatalar ve Çözümleri
Hata 1: const ile tanımlanmış değişkeni değiştirmeye çalışmak
// ❌ Hata
const isim = "Ali";
isim = "Veli"; // TypeError: Assignment to constant variable
// ✅ Çözüm — değişecekse let kullanın
let isim2 = "Ali";
isim2 = "Veli"; // Sorun yokHata 2: Tanımlanmamış değişkeni kullanmak
// ❌ Hata
console.log(sehir); // ReferenceError: sehir is not defined
// ✅ Çözüm — önce tanımlayın
let sehir = "İstanbul";
console.log(sehir);Hata 3: String ve Number karıştırmak
// ❌ Beklenmedik sonuç
let fiyat = "100";
let kdv = 18;
let toplam = fiyat + kdv;
console.log(toplam); // "10018" — string birleştirme oldu!
// ✅ Çözüm — önce number'a dönüştürün
let toplamDoğru = Number(fiyat) + kdv;
console.log(toplamDoğru); // 118Özet
🔹 `const` varsayılan tercih olmalı (değer değişmeyecekse), `let` değer değişecekse kullanılır, `var` asla kullanılmaz
🔹 JavaScript'te 7 primitive tip vardır: string, number, boolean, null, undefined, symbol, bigint — hepsi değiştirilemez (immutable)
🔹 `typeof` operatörü tipi sorgulamak için kullanılır, ama
typeof null === "object"vetypeof [] === "object"tuzaklarına dikkat🔹 Primitive değerler kopyalandığında değer kopyalanır, referans tiplerde (object, array) adres kopyalanır — bu fark birçok hatanın kaynağıdır
🔹 Template literal (backtick) ile string birleştirme çok daha okunabilir ve güçlüdür: `
Merhaba, ${isim}!`🔹 Floating point hassasiyet sorunu gerçek bir problemdir — para hesaplamalarında tam sayı (kuruş) kullanın
AI Asistan
Sorularını yanıtlamaya hazır