Mert Özen Her Satırda Daha İleri
Frontend JavaScript Temel — #04

JavaScript Veri Tipleri: Primitive'ler, Object ve typeof

Mert Özen 3 Kas 2026 8 dk 4 görüntülenme
JavaScript Veri Tipleri: Primitive'ler, Object ve typeof

JavaScript'in yedi primitive tipini ve object'i tanıyor, typeof'un neden null için "object" dediğini, primitive'lerin değişmezliğini ve değer ile referans farkını örneklerle görüyoruz.

Sürüm notu: Bu yazıdaki kodlar ES2026 ve güncel tarayıcılar (Chrome, Edge, Firefox, Safari) içindir.

Önce Tahmin Et

typeof operatörü, bir değerin tipini bir string olarak söyler. Üç değere soralım:

console.log(typeof null);
console.log(typeof []);
console.log(typeof function () {});

Bu üç satır konsola ne yazdırır? null için "null", array için "array", fonksiyon için "function" mı bekliyorsun? Okumaya devam etmeden önce bir tahmin yap. Üçünün de cevabını, JavaScript'teki tipleri tek tek tanıdıktan sonra vereceğiz.

Değişkenin Değil, Değerin Tipi Var

Daha önce gördüğümüz değişkenleri etiketlere benzetmiştik. Etiketin kendisinin bir tipi yok; tip, kutunun içindeki değere ait. Bu yüzden aynı değişkene önce bir sayı, sonra bir metin koyabilirsin. Bunu tarayıcının konsoluna yapıştırıp dene:

let value = 42;
console.log(typeof value);
value = "forty-two";
console.log(typeof value);

Önce "number", sonra "string" göreceksin. Bu davranışa dinamik tipleme denir. Motor her işlemde değerin o anki tipine bakar ve ona göre davranır. Esnek bir sistem, ama bir bedeli var: tipleri sen takip etmezsen motor da senin yerine uyarmaz. O yüzden JavaScript'te hangi tiplerin olduğunu ve her birinin nasıl davrandığını bilmek şart.

JavaScript'te sekiz tip var. Yedisi primitive, yani tek ve basit bir değer taşıyan tiplerdir: string, number, bigint, boolean, undefined, null ve symbol. Sekizincisi ise object. Önce primitive'lere bakalım.

string, number, boolean: Her Gün Kullandıkların

Bu üçü kodunun büyük bölümünü oluşturacak:

const city = "Istanbul";
const district = 'Kadikoy';
const floorCount = 12;
const temperature = 18.5;
const isOpen = true;
console.log(typeof city, typeof floorCount, typeof temperature, typeof isOpen);

Çıktı string number number boolean. String bir metindir; çift tırnak ya da tek tırnak arasına yazılır, ikisi de aynı işi görür. Ters tırnaklı template literal'i ve string'lerin bütün inceliklerini ilerleyen yazılarda detaylandıracağız.

Number tam sayıyı da ondalıklı sayıyı da kapsar. Birçok dilde ikisi ayrı tiplerdir, JavaScript'te ise tek bir number tipi var: 12 de 18.5 de number. Ondalık sayılarda ayrıca küçük hassasiyet sürprizleri çıkar; onları sayılar yazısında göreceğiz.

Boolean'ın yalnızca iki değeri vardır: true ve false. Evet ya da hayır, açık ya da kapalı. Koşullarda ve karşılaştırmalarda sürekli karşına çıkacak.

undefined ve null: İki Farklı Boşluk

JavaScript'te "değer yok" demenin iki yolu var ve ikisi aynı şey değil:

let address;
console.log(address);
let selectedProduct = null;
console.log(selectedProduct);

İlk satır undefined, ikincisi null yazdırır. Farkı bir otel resepsiyonuyla düşün. undefined, hiç doldurulmamış bir kayıt formundaki boş satırdır; kimse oraya bir şey yazmadı. null ise görevlinin bilerek "boş oda yok" diye yazdığı satırdır; orada bir cevap var ve cevap "hiçbir şey".

Pratikte motor undefined'ı kendisi üretir: değer verilmemiş bir değişken, object'te olmayan bir property, bir şey döndürmeyen bir fonksiyonun sonucu. null'ı ise genellikle sen yazarsın, "burada bilinçli olarak bir değer yok" demek için. Basit bir kural: bir şeyi kasıtlı olarak boşaltacaksan null kullan, undefined'ı motora bırak.

bigint ve symbol: Az Görülen İkili

Number tipinin bir sınırı var. Belli bir büyüklükten sonra tam sayıları doğru tutamaz. Konsolda dene:

console.log(Number.MAX_SAFE_INTEGER);
console.log(9007199254740991 + 2);
console.log(9007199254740991n + 2n);

Number.MAX_SAFE_INTEGER, number'ın güvenle tutabildiği en büyük tam sayı: 9007199254740991. Buna 2 eklediğinde 9007199254740993 beklersin ama 9007199254740992 çıkar. Sonuna n eklediğin sayılar ise ES2020 ile gelen bigint tipindendir ve istediğin kadar büyük tam sayıyı hatasız tutar; üçüncü satır doğru sonucu, 9007199254740993n değerini verir. Dikkat: bigint ile number'ı aynı işlemde karıştıramazsın. 10n + 1 yazarsan TypeError: Cannot mix BigInt and other types, use explicit conversions alırsın.

Symbol ise ES2015 ile geldi ve her biri benzersiz bir değer üretir:

const id1 = Symbol("id");
const id2 = Symbol("id");
console.log(id1 === id2);
console.log(typeof id1);

Açıklamaları aynı olsa da iki symbol birbirine eşit değil; çıktı false ve "symbol". Symbol'ler çoğunlukla object'lere, başka hiçbir kodla çakışmayacak gizli anahtarlar eklemek için kullanılır. Günlük kodda nadiren yazacaksın; asıl gücünü ilerleyen yazılarda, iterator'ları konuşurken göreceğiz.

object: Geri Kalan Her Şey

Primitive olmayan her şey object'tir. Süslü parantezle yazdığın object'ler, köşeli parantezle yazdığın array'ler, fonksiyonlar, tarihler; hepsi bu çatının altında:

const user = { name: "Ada", age: 31 };
const colors = ["red", "green"];
const today = new Date();
console.log(typeof user, typeof colors, typeof today);

Üçü için de cevap "object". Primitive tek bir değer taşırken object birden fazla değeri bir arada tutan bir kaptır. Object'leri, array'leri ve tarihleri ilerleyen yazılarda tek tek detaylandıracağız. Bu yazıda bilmen gereken, bu ayrımın değerlerin kopyalanma biçimini de değiştirdiği; birazdan ona geleceğiz.

typeof ve null'un Tuhaf Cevabı

Artık baştaki soruya dönebiliriz. Cevaplar sırasıyla "object", "object" ve "function".

Array'in "object" çıkması mantıklı, çünkü az önce gördüğümüz gibi array de bir object. Bir değerin array olup olmadığını öğrenmek istiyorsan typeof işe yaramaz; bunun için Array.isArray(colors) kullanırsın ve true cevabını alırsın.

Fonksiyonlar da aslında object'tir, ama çağrılabilen özel bir türü oldukları için typeof onlara ayrıca "function" der. Bu bir kolaylık; bir değerin çağrılabilir olup olmadığını tek satırda anlamanı sağlar.

typeof null'ın "object" vermesi ise düpedüz bir hata. JavaScript'in ilk sürümünde değerler bellekte küçük bir tip etiketiyle tutuluyordu ve object'lerin etiketi sıfırdı. null da tamamen sıfırlardan oluşan bir değer olarak temsil edildiği için typeof ona bakıp "object" dedi. Hata yıllar önce fark edildi, ama düzeltilirse bu davranışa güvenen sayısız web sitesi bozulacaktı. Web'in temel kuralı "eski sayfaları kırma" olduğu için hata standarda olduğu gibi girdi ve hâlâ orada duruyor.

Pratik sonuç: bir değerin null olup olmadığını typeof ile değil, doğrudan value === null ile kontrol et. ==='ü bir sonraki yazıda ayrıntısıyla göreceğiz. Şunu da ekleyelim: typeof her zaman bir string döndürür. Yani typeof typeof 42 yazarsan cevap "string" olur.

Primitive'ler Değişmez, Değerler Kopyalanır

Primitive'lerin önemli bir özelliği var: değişmezler. Bir string'in tek bir harfini yerinde değiştiremezsin:

let word = "desk";
word[0] = "K";
console.log(word);
console.log(word.toUpperCase());
console.log(word);

Çıktı desk, DESK, desk. İkinci satır hiçbir şeyi değiştirmedi ve normal modda sesini bile çıkarmadı; daha önce gördüğümüz strict mode'da ise TypeError alırdın. toUpperCase() da orijinal string'e dokunmadı, büyük harfli yeni bir string üretip döndürdü. String'i değiştirmenin tek yolu değişkene yeni bir değer atamak: word = "disk".

Peki word bir primitive iken üzerinde nasıl toUpperCase() gibi bir method çağırabildik? Motor bu anlık iş için arka planda geçici bir sarmalayıcı (wrapper) object oluşturur, method'u çalıştırır ve object'i atar. Sen bunu hiç fark etmezsin.

Bu değişmezlik, kopyalama davranışını da belirliyor. Konsolda karşılaştır:

let a = 10;
let b = a;
b = 20;
console.log(a, b);

const box1 = { color: "red" };
const box2 = box1;
box2.color = "blue";
console.log(box1.color);

İlk çıktı 10 20. b = a dediğinde değerin bir kopyası alındı; b'yi değiştirmek a'yı etkilemedi. İkinci çıktı ise blue. box2 = box1 object'in kopyasını almadı, aynı object'i gösteren ikinci bir isim oluşturdu.

Bunu bir fotokopiyle bir ev adresi arasındaki fark gibi düşün. Primitive'i kopyalamak fotokopi çekmektir; kopyanın üstüne ne karalarsan karala, aslı temiz kalır. Object'i kopyalamak ise ev adresini başka bir kâğıda yazmaktır. İki kâğıt da aynı evi gösterir; birinin adresine gidip duvarı maviye boyarsan, öbür adrese giden de mavi duvar görür. Buna referans ile çalışmak denir. Bu konuyu object'ler ve array'ler yazılarında, kopyalama yöntemleriyle birlikte derinleştireceğiz.

Sık Düşülen Tuzaklar

null'ı typeof ile kontrol etmek. typeof value === "object" kontrolü null için de true döner. Bir object beklediğin yerde null geldiğinde bu kontrol seni yanıltır ve bir sonraki satırda hata alırsın.

Array'i typeof ile tanımaya çalışmak. Array için cevap her zaman "object". Array kontrolü için Array.isArray kullan.

"42" ile 42'yi aynı sanmak. Biri string, biri number. Kullanıcıdan gelen veriler, örneğin bir formdaki kutuya yazılan sayı, çoğu zaman string olarak gelir. Daha önce gördüğümüz "2" + 2 örneğinin "22" vermesi de tam olarak bu yüzden.

NaN'ın tipini yanlış tahmin etmek. "Not a Number" anlamına gelen NaN, tuhaf ama typeof NaN sorusuna "number" cevabını verir. Geçersiz bir sayısal işlemin sonucu da yine bir number'dır. Sayılar yazısında buna geri döneceğiz.

Object kopyaladığını sanmak. const copy = original bir object'i kopyalamaz, sadece ona ikinci bir isim verir. Yeni isim üzerinden yaptığın her değişiklik orijinali de değiştirir.

Küçük Bir Deneme

★☆☆ Yedi primitive tipin her biri için bir değişken oluştur ve hepsini typeof ile konsola yazdır. Hangisi beklediğin cevabı vermedi?

★★☆ Çalıştırmadan önce her satırın çıktısını tahmin et:

console.log(typeof typeof 42);
console.log(typeof NaN);
console.log(typeof undefined);
console.log(typeof 10n);
console.log(Array.isArray([]));

★★★ Aşağıdaki kodu çalıştırmadan önce iki console.log'un çıktısını tahmin et. Sonra çalıştır ve sonucu fotokopi ile adres benzetmesiyle kendi cümlelerinle açıkla:

let firstName = "Grace";
let nickname = firstName;
nickname = "Gracie";

const profile = { name: "Grace" };
const backup = profile;
backup.name = "Gracie";

console.log(firstName, nickname);
console.log(profile.name, backup.name);

Artık elindeki değerlerin hangi tipte olduğunu ve nasıl kopyalandığını biliyorsun. Bir sonraki yazıda bu değerlerle işlem yapmaya geçiyoruz: aritmetik ve karşılaştırma operatörleri, == ile === arasındaki fark, truthy/falsy değerler ve ?? operatörü.