JavaScript'te yedi ilkel (primitive) veri tipi vardır: Number, BigInt, String, Boolean, Symbol, Undefined ve Null. Bunların dışındaki her şey, diziler ve fonksiyonlar dahil, Object tipindedir. Bir değerin tipini typeof operatörüyle öğrenebilirsiniz; tek tuhaf istisna typeof null ifadesinin "object" döndürmesidir.

Bu yazıda ilkel değerlerle nesneler arasındaki temel farkı, typeof operatörünün tüm olası sonuçlarını ve günlük kodda sık karşılaşılan tip tuzaklarını örneklerle inceliyoruz.

Dinamik ve zayıf tipleme

JavaScript dinamik tipli bir dildir: tip değişkene değil değere aittir. Aynı değişkene önce sayı, sonra metin, sonra boolean atayabilirsiniz. Dil aynı zamanda zayıf tiplidir; uyumsuz tipler aynı işlemde buluştuğunda hata vermek yerine örtük dönüşüm yapar.

javascript
let deger = 42;
console.log(typeof deger); // number
deger = "kırk iki";
console.log(typeof deger); // string

const sonuc = 42 + "1";
console.log(sonuc, typeof sonuc); // 421 string

Örtük dönüşümler kullanışlı olsa da beklenmedik yerlerde hata kaynağı olabilir. Kuralların tamamı tip dönüşümü yazısında anlatılıyor.

Yedi ilkel tip ve typeof sonuçları

TipÖrnek değertypeof sonucuSarmalayıcı nesne
Nullnull"object"yok
Undefinedundefined"undefined"yok
Booleantrue, false"boolean"Boolean
Number42, 3.14, NaN, Infinity"number"Number
BigInt42n"bigint"BigInt
String"metin""string"String
SymbolSymbol("id")"symbol"Symbol

typeof için olası sonuçlar bunlarla sınırlı değil: çağrılabilen nesneler (fonksiyonlar ve sınıflar) "function", diğer tüm nesneler "object" döndürür. MDN, bu listenin eksiksiz olduğunu ve spesifikasyona uyan hiçbir motorun başka bir değer üretmediğini belirtir.

javascript
console.log(typeof undefined);    // undefined
console.log(typeof true);         // boolean
console.log(typeof 42);           // number
console.log(typeof NaN);          // number
console.log(typeof 42n);          // bigint
console.log(typeof "metin");      // string
console.log(typeof Symbol("id")); // symbol
console.log(typeof null);         // object
console.log(typeof {});           // object
console.log(typeof []);           // object
console.log(typeof function () {}); // function
console.log(typeof class {});     // function
console.log(typeof typeof 1);     // string

İlkel tiplere kısa bakış

İlkel tiplere kısa bakış: Number ve BigInt, String, Boolean ve Symbol, undefined ve null

Number ve BigInt

Number, IEEE 754 standardındaki 64 bit çift duyarlıklı kayan nokta değeridir; tam sayılar ve ondalıklı sayılar aynı tipi kullanır. Tam sayılar yalnızca Number.MIN_SAFE_INTEGER ile Number.MAX_SAFE_INTEGER (253 - 1) arasında güvenle temsil edilir. Bu tipin Infinity, -Infinity, -0 ve kendisine eşit olmayan tek değer olan NaN gibi özel değerleri de vardır. BigInt ise keyfi büyüklükte tam sayılar içindir ve sayının sonuna n eklenerek yazılır. İki tip aritmetik işlemde karıştırılamaz.

javascript
console.log(Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2); // true
const buyuk = BigInt(Number.MAX_SAFE_INTEGER);
console.log(buyuk + 1n === buyuk + 2n); // false

try {
  console.log(1n + 1);
} catch (e) {
  console.log(e.name); // TypeError
}

Sayı tiplerinin sınırları ve ondalık hassasiyeti için Number ve BigInt yazısına bakın.

String

Metinler UTF-16 kod birimlerinden oluşan bir dizidir ve değiştirilemez. length özelliği kod birimi sayısını verir; bu sayı her zaman ekrandaki karakter sayısıyla aynı olmayabilir. Metin işlemleri için string metotları ve template literal yazılarına göz atabilirsiniz.

Boolean ve Symbol

Boolean yalnızca true ve false değerlerini alır. Symbol ise her çağrıda benzersiz ve değiştirilemez bir değer üretir; genellikle başka kodla çakışmayacak özellik anahtarları oluşturmak için kullanılır. Ayrıntılar Symbol nedir yazısında.

javascript
console.log(Symbol("id") === Symbol("id")); // false
console.log(Boolean(""), Boolean("0"));        // false true

undefined ve null

İkisi de "değer yok" anlamı taşısa da kullanım yerleri farklıdır. undefined dilin varsayılan boşluğudur: değer verilmeden bildirilen değişken, var olmayan bir özellik, değer döndürmeyen fonksiyon ve bulunamayan eleman için find() gibi metotlar undefined üretir. null ise genellikle kasıtlı olarak boş bırakılmış bir nesne yerini gösterir; dilin içinde en önemli kullanımı prototip zincirinin sonudur. Ayrıca null bir anahtar kelimedir, undefined ise global bir özellik olan sıradan bir tanımlayıcıdır.

javascript
let tanimsiz;
console.log(tanimsiz);                       // undefined
console.log({}.olmayan);                     // undefined
console.log((function () {})());             // undefined
console.log([1, 2].find((x) => x > 5));      // undefined
console.log(Object.getPrototypeOf(Object.prototype)); // null

typeof null neden "object" döndürür?

typeof null neden "object" döndürür?

Bu davranış JavaScript'in ilk sürümünden kalmadır. İlk uygulamada değerler bir tip etiketi ve bir değer olarak saklanıyordu; nesnelerin tip etiketi 0 idi. null çoğu platformda sıfır adresli NULL işaretçisiyle temsil edildiği için onun etiketi de 0 olarak okundu ve typeof null sonucu "object" oldu. Bunu düzeltmek için bir öneri yapılmış ama kabul edilmemiştir, çünkü değişiklik mevcut kodu bozardı.

Pratikteki sonucu şudur: bir değerin null olup olmadığını typeof ile değil, doğrudan === null karşılaştırmasıyla kontrol edin. Benzer şekilde diziler de "object" döndürdüğü için dizi kontrolü Array.isArray() ile yapılmalıdır.

javascript
function nesneMi(deger) {
  return typeof deger === "object" && deger !== null;
}
console.log(nesneMi({}));   // true
console.log(nesneMi(null)); // false
console.log(Array.isArray([1, 2])); // true
console.log(Array.isArray({ length: 2 })); // false

İlkel değerler değiştirilemez

Nesne dışındaki tüm tiplerin değerleri değiştirilemezdir (immutable). Bir metnin karakterini atamayla değiştiremezsiniz; toUpperCase() gibi metotlar her zaman yeni bir değer döndürür. Örnekteki ikinci satır Türkçe için de önemli bir ayrıntıyı gösteriyor: toUpperCase() dil kurallarını hesaba katmadan çevirir, Türkçe büyük harf kuralları için toLocaleUpperCase("tr") kullanılır. Değişkene yeni bir değer atamak ise değeri değiştirmek değil, değişkeni başka bir değere bağlamaktır.

javascript
const kelime = "kedi";
const buyukHarf = kelime.toUpperCase();
console.log(kelime, buyukHarf); // kedi KEDI
console.log(kelime.toLocaleUpperCase("tr")); // KEDİ

const s = "abc";
s[0] = "X"; // strict mode dışında etkisiz
console.log(s); // abc

İlkel bir değerin özelliğine eriştiğinizde (örneğin "abc".length) JavaScript değeri geçici olarak ilgili sarmalayıcı nesneye sarar ve özelliği o nesneden okur. null ve undefined için sarmalayıcı olmadığından bunların özelliğine erişmek TypeError fırlatır. Bu tür erişimleri güvenli hale getirmek için optional chaining kullanılabilir.

Nesneler: değiştirilebilir ve kimlikle karşılaştırılır

JavaScript'te değiştirilebilir (mutable) olan tek değer türü nesnelerdir. Fonksiyonlar da çağrılabilme yeteneği olan nesnelerdir. Bir nesneyi başka bir değişkene atadığınızda nesne kopyalanmaz; iki değişken aynı nesneye başvurur. Bu yüzden içerikleri aynı olan iki ayrı nesne birbirine eşit sayılmaz.

javascript
const a = { ad: "Ada" };
const b = a;          // aynı nesne
b.ad = "Ece";
console.log(a.ad);    // Ece

const c = { ad: "Ece" };
console.log(a === b); // true
console.log(a === c); // false (içerik aynı, nesne farklı)

Nesne özelliklerinin anahtarları yalnızca metin veya Symbol olabilir. Anahtar olarak sayı kullandığınızda değer örtük olarak metne çevrilir; bu yüzden obj[1] ile obj["1"] aynı özelliği gösterir.

javascript
const nesne = {};
nesne[1] = "bir";
console.log(nesne["1"]);         // bir
console.log(Object.keys(nesne)); // [ '1' ]

Nesneleri kopyalamanın ve parçalamanın yolları destructuring ve spread, nesnelerle çalışan yerleşik metotlar ise Object metotları yazısında anlatılıyor.

Sarmalayıcı nesneleri new ile oluşturmayın

new Number(1), new String("abc") veya new Boolean(false) ilkel değer değil nesne üretir. MDN bu kullanımı kafa karıştırıcı ve gereksiz bulur. Özellikle new Boolean(false) tehlikelidir: tüm nesneler koşullarda doğru (truthy) sayıldığı için bu nesne if içinde true gibi davranır.

javascript
const sarili = new Boolean(false);
console.log(typeof sarili); // object
if (sarili) {
  console.log("nesne olduğu için truthy"); // nesne olduğu için truthy
}
console.log(typeof Number("5")); // number (new olmadan çağrı ilkel döndürür)

Hangi kontrol için hangi yöntem?

Hangi kontrol için hangi yöntem? Değer null mı?, Değer undefined mı?, null veya undefined mı?, Dizi mi?

typeof çoğu ilkel tip için yeterlidir, ancak birkaç durumda daha uygun bir araç vardır. Aşağıdaki tablo günlük kodda en sık ihtiyaç duyulan kontrolleri özetliyor:

SoruÖnerilen kontrol
Değer null mı?deger === null
Değer undefined mı?deger === undefined
null veya undefined mı?deger == null ya da deger ?? varsayilan
Dizi mi?Array.isArray(deger)
NaN mı?Number.isNaN(deger)
Fonksiyon mu?typeof deger === "function"
null olmayan bir nesne mi?typeof deger === "object" && deger !== null

Sık yapılan hatalar

  • typeof deger === "object" ile nesne kontrolü: null da bu testi geçer; deger !== null koşulunu ekleyin.
  • Dizileri typeof ile ayırt etmeye çalışmak: sonuç "object" olur; Array.isArray() kullanın.
  • NaN değerinin sayı olmadığını düşünmek: typeof NaN sonucu "number"dır. Kontrol için Number.isNaN() kullanın; ayrıntılar eşitlik operatörleri yazısında.
  • BigInt ile Number'ı aynı işlemde kullanmak: TypeError alırsınız; birini açıkça diğerine dönüştürün.
  • Nesneleri === ile içerik bakımından karşılaştırmak: bu operatör kimlik karşılaştırır, içerik değil.

Sık Sorulan Sorular

JavaScript'te kaç veri tipi vardır?

Spesifikasyon sekiz tip tanımlar: yedi ilkel tip (Undefined, Null, Boolean, String, Symbol, Number, BigInt) ve Object. Dizi, fonksiyon, Date, Map gibi yapılar ayrı tip değil, Object tipinin farklı türleridir.

null ile undefined arasındaki fark nedir?

undefined bir değerin henüz verilmediğini, null ise bilinçli olarak boş bırakıldığını anlatmak için kullanılır. İkisi == ile birbirine eşittir ama === ile eşit değildir.

Dizi ayrı bir veri tipi mi?

Hayır. Diziler, sayısal anahtarlar ve length özelliği üzerinden çalışan özel nesnelerdir. Bu yüzden typeof sonucu "object"dir.

typeof NaN neden "number" döndürür?

NaN, Number tipinin tanımlanamayan sonuçlar için ayrılmış özel bir değeridir. Adı "sayı değil" anlamına gelse de tipi Number'dır.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: JavaScript öğrenme rehberi · Tip dönüşümü · Eşitlik operatörleri · Number ve BigInt · Symbol nedir