İçeriğe geç
academia.sh

Ders 08 / 21

Tip Dönüşümü ve Zorlama

Açık dönüşüm ile örtük zorlamanın ayrımı; sayıya, metne ve ilkel değere çevirme yordamları; toplama işlecinin iki yüzü ve metinden veri okuma.

İçindekiler

Önceki ders, iki sayı tipinin aritmetik işleçlerde karıştırılmasının reddedildiğini gösterdi. Bu, dilin genel kuralı değildir; istisnadır. Dilin geri kalanında tipler kendiliğinden dönüştürülür ve sonuç, dönüşümün hangi sırayla yapıldığına bağlıdır.

Programlama Temelleri kursundaki Tip Dönüşümü dersinde açık dönüşüm ile örtük dönüşüm ayrımı kurulmuştu. Bu ders o ayrımı JavaScript’e uygular ve örtük dönüşümün — bu kursta zorlama (coercion) adıyla anılacak olan davranışın — adımlarını tanımlar. Amaç sonuçları ezberlemek değil, sonucu üreten yordamı izleyebilmektir.

Üç Hedef Tip

Zorlama her zaman üç hedeften birine doğrudur: sayı, dizgi veya mantıksal değer. Standart bunlar için üç soyut işlem tanımlar. Bu derste ilk ikisi ele alınacak; mantıksal değere çevirme Doğruluk Değerleri dersinin konusudur.

Sayıya çevirme yordamı, her ilkel tip için sabit bir kural verir:

console.log(Number("21.5"));
console.log(Number(""));
console.log(Number("   "));
console.log(Number("21.5 C"));
console.log(Number(null));
console.log(Number(undefined));
console.log(Number(true), Number(false));
21.5
0
0
NaN
0
NaN
1 0

Dört satır dikkat ister. Boş dizgi ve yalnızca boşluk içeren dizgi sıfır verir — metnin “sayı içermemesi”, sıfır sayılmasıyla sonuçlanır. Sayıyla başlayıp harfle süren metin ise NaN verir; yordam metnin tamamının geçerli bir sayı yazımı olmasını ister. null sıfıra, undefined ise NaN’a çevrilir; iki yokluk değerinin ayrımı burada da sürüyor.

Metne çevirme yordamı da tip başına tanımlıdır:

console.log(String(21.5));
console.log(String(null), String(undefined), String(true));
console.log(String([1, 2, 3]));
console.log(String([]));
console.log(String([null, undefined, 3]));
console.log(String({ a: 1 }));
21.5
null undefined true
1,2,3

,,3
[object Object]

Diziler elemanlarını virgülle birleştirir; boş dizi boş metin verir. Dizi içindeki null ve undefined değerleri boş metne çevrilir — dördüncü satırdaki iki baştaki virgül bundandır. Sıradan nesneler ise içeriklerini göstermez; [object Object] sabit metnini verir.

Nesneden İlkel Değere

Yukarıdaki dizi ve nesne sonuçları ara bir adımdan geçer. Bir nesne sayı veya metin bekleyen bir yere girdiğinde, önce ilkel değere çevrilir. Bu çevrim, nesnenin iki yöntemini belirli bir sırayla dener: sayısal bağlamda önce değer üreten yöntem, metinsel bağlamda önce metin üreten yöntem çağrılır.

Davranış doğrudan gözlemlenebilir:

const nesne = {
  valueOf() { return 42; },
  toString() { return "kirk iki"; },
};
console.log(nesne * 2);
console.log(String(nesne));
console.log(nesne + 1);
84
kirk iki
43

Çarpma sayısal bağlamdır: değer üreten yöntem çağrıldı. Metne çevirme metinsel bağlamdır: metin üreten yöntem çağrıldı. Üçüncü satır ise toplama işlecinin özel durumudur; bir sonraki bölümün konusudur.

Sıradan bir nesnede değer üreten yöntem nesnenin kendisini döndürür — yani ilkel bir değer vermez. Bu yüzden sıra metin üreten yönteme geçer ve [object Object] çıkar. Diziler metin üreten yöntemi elemanları birleştirecek biçimde tanımladığı için 1,2,3 verir.

Toplama İşlecinin İki Yüzü

Toplama işleci diğer aritmetik işleçlerden ayrılır. Adımları şöyledir: her iki işlenen ilkel değere çevrilir; ikisinden biri dizgi ise sonuç metin birleştirmesidir, değilse her ikisi sayıya çevrilir ve toplanır.

console.log(1 + 2);
console.log("1" + 2);
console.log(1 + 2 + "3");
console.log("1" + 2 + 3);
3
12
33
123

Son iki satır, işlecin soldan sağa birleştiğini gösterir. Üçüncü satırda 1 + 2 önce sayısal olarak hesaplanır, sonra 3 sonucu metne çevrilip birleştirilir. Dördüncü satırda ilk işlem zaten birleştirmedir; sonuç dizgi olduğu için ikinci işlem de birleştirme olur. İşlem sırası, sonucun tipini belirliyor.

Diğer aritmetik işleçlerde bu ikilik yoktur; her zaman sayıya çevirirler:

console.log("21.5" - 1);
console.log("21.5" * 2);
console.log(1 + null);
console.log(1 + undefined);
console.log(true + true);
20.5
43
1
NaN
2

Üçüncü ve dördüncü satırlar sayıya çevirme kurallarının doğrudan sonucudur: null sıfır, undefined ise NaN verir ve NaN içeren her aritmetik işlem NaN üretir.

Sık alıntılanan ifadeler de aynı iki adımdan çıkar:

console.log([] + {});
console.log([] + []);
[object Object]

Birinci satır: boş dizi ilkel değere çevrilince boş metin, nesne çevrilince [object Object] olur; biri dizgi olduğu için birleştirme yapılır. İkinci satır: iki boş metin birleşir ve boş satır yazılır. Ortada gizem yoktur — yalnızca iki adımlı bir yordam vardır.

Açık Dönüşüm Araçları

Zorlamaya güvenmek yerine dönüşümü yazmak, kodun okunmasını kolaylaştırır. Dört araç ayırt edilmelidir:

console.log(parseInt("21.5 C"), parseFloat("21.5 C"));
console.log(parseInt("  42px"), Number("  42px"));
console.log(parseInt(""), Number(""));
console.log(parseInt("1f", 16));
console.log(+"21.5", +"", +"abc");
21 21.5
42 NaN
NaN 0
31
21.5 0 NaN

Number, metnin tamamının geçerli olmasını ister; geçersizse NaN verir, boş metni sıfır sayar. parseInt ve parseFloat ise baştan başlayıp gidebildiği kadar okur; geri kalanı yok sayar, hiç okuyamazsa NaN verir. parseInt ayrıca bir taban parametresi alır; Bilgisayarlar Nasıl Çalışır kursundaki Onaltılık ve Sekizlik Tabanlar dersindeki gösterimler bu parametreyle okunur.

Tek terimli artı işleci Number ile aynı kuralı uygular; kısalığı okunaklılığın önüne geçtiği için kursta kullanılmayacaktır.

İki aracın seçimi veriye bağlıdır. Alan “yalnızca sayı içermeli” ise Number doğru seçimdir: bozuk veriyi NaN ile bildirir. Alan “sayıyla başlayan bir metin” ise parseFloat doğru seçimdir. Yanlış seçim, bozuk verinin sessizce geçmesine yol açar.

Ölçüm Betiğine Uygulama

Ölçüm kayıtları çoğunlukla metin olarak gelir. Aşağıdaki betik, noktalı virgülle ayrılmış satırları okuyup sayısal alanları çevirir:

const satirlar = ["A1;21.5;48", "A2;19.75;55", "B1;;41", "B2;abc;60"];

for (const satir of satirlar) {
  const [istasyon, sicaklikMetni, nemMetni] = satir.split(";");
  const sicaklik = Number(sicaklikMetni);
  const nem = Number(nemMetni);
  console.log(istasyon, sicaklik, nem, Number.isNaN(sicaklik));
}
A1 21.5 48 false
A2 19.75 55 false
B1 0 41 false
B2 NaN 60 true

Son iki satır, verinin iki farklı bozukluğunu gösteriyor ve yalnızca biri yakalanıyor.

B2 kaydında sıcaklık alanı abc yazıyor; Number bunu NaN yaptı ve Number.isNaN denetimi durumu bildirdi. B1 kaydında ise sıcaklık alanı boştur ve Number boş metni sıfıra çevirdi. Sıfır geçerli bir sıcaklık değeridir; denetim bu kaydı sağlam sandı. Eksik ölçüm, sessizce sıfır dereceye dönüştü.

Doğru davranış, dönüşümden önce alanın boş olup olmadığını sınamaktır:

function sicaklikOku(metin) {
  if (metin.trim() === "") {
    return null;
  }
  const deger = Number(metin);
  return Number.isNaN(deger) ? null : deger;
}

for (const alan of ["21.5", "", "   ", "abc", "0"]) {
  console.log(JSON.stringify(alan), "->", sicaklikOku(alan));
}
"21.5" -> 21.5
"" -> null
"   " -> null
"abc" -> null
"0" -> 0

Boş alan ile bozuk alan artık ayrı ayrı yakalanıyor ve geçerli bir sıfır ölçümü korunuyor. Son satır bu yüzden önemlidir: sıfır, eksik veri değildir.

Aynı işi daha kısa yazma girişimi tam bu noktada kırılır:

function sicaklikOkuKisa(metin) {
  const deger = Number(metin);
  return deger ? deger : null;
}

for (const alan of ["21.5", "", "abc", "0"]) {
  console.log(JSON.stringify(alan), "->", sicaklikOkuKisa(alan));
}
"21.5" -> 21.5
"" -> null
"abc" -> null
"0" -> null

Üç satır doğru, sonuncusu yanlıştır: geçerli bir sıfır ölçümü eksik veriye dönüştü. Nedeni dönüşüm değil, koşulun 0 değerini nasıl değerlendirdiğidir. Bu davranışın kuralı Doğruluk Değerleri dersinde tanımlanacak.

Eksik değer için null seçilmesi bilinçlidir: İlkel Tipler dersindeki ayrım gereği null, “ölçülmedi” bilgisini taşır; undefined ise alanın hiç bulunmadığını söylerdi.

Özet

  • Zorlama üç hedefe doğrudur: sayı, dizgi ve mantıksal değer. Her hedef için standartta adım adım tanımlı bir yordam vardır.
  • Sayıya çevirmede boş dizgi sıfır, geçersiz metin NaN, null sıfır, undefined NaN verir.
  • Nesneler önce ilkel değere çevrilir; sayısal bağlamda değer üreten, metinsel bağlamda metin üreten yöntem önceliklidir.
  • Toplama işleci, işlenenlerden biri ilkel değere çevrildikten sonra dizgi ise birleştirme yapar; diğer aritmetik işleçler her zaman sayıya çevirir.
  • Number metnin tamamını ister, parseInt/parseFloat gidebildiği kadar okur; alanın anlamına göre seçilirler.
  • Boş metnin sıfıra çevrilmesi, eksik ölçümü geçerli bir değere dönüştürür; dönüşümden önce boşluk denetimi gerekir.

Sonraki Adım

Bu derste sicaklik === null benzeri karşılaştırmalar kullanıldı ama kuralları tanımlanmadı. Sonraki ders üç karşılaştırma işlecini adım adım ele alacak: tip karşılaştıran katı eşitlik, zorlama uygulayan gevşek eşitlik ve NaN ile -0 durumlarını ayıran değer eşitliği. Gevşek eşitliğin adımları, bu dersteki zorlama yordamlarının doğrudan devamıdır.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat