Photo by Sam Loyd on Unsplash

JS Tarihcesi

Javascript’ te prototype, __proto__ Kavramlarını Anlamak

Onur Dayıbaşı
Frontend Development With JS
4 min readFeb 8, 2021

--

Bu konu uzun zamandır benimde kafamı kurcalayan ama üzerinde bir takım temeller oluşturmadan anlaşılacak bir konu değil. Bunun için öncesinde aşağıdaki konularda bilgi birikimi oluşturmam gerekiyordu.

Not: Bu yazıda önemli olan kısımları diğer yazılardan alarak, kopyalarak bu yazı içerisine taşıyacağım için aşağıdaki yazıları okumanıza gerek yok. Aşağıdaki bilgileri bu yazının altyapısının hangi yazılar üzerinden geldiğini anlatmak için bu listelemeyi yapıyorum.

  • Scope Chain konusunun detaylarını bu yazıdan ulaşabilirsiniz.
  • Prototype Chain konusunun detaylarına bu yazıdan ulaşabilirsiniz.
  • Data yapısının Primitive ve Object olarak 2'ye ayrıldığını ve Array, Date, Function vb.. yapıların Object Prototype Chain üzerine kurulan bir yapı olduğunu bu yazıdan ulaşabilirsiniz.
  • this ve new kavramları fonksiyonlarda nasıl kullanıldığını bu yazıdan okuyabilirsiniz.

Öncelikle problemi anlayalım ? JavaScript te bir user objesi oluşturup, sayHello fonksiyonu nu çağırınca bu user içerisindeki ad bilgisinini kullanarak console bir takım bilgiler yazmasını istiyoruz. Bunun bir kaç yolu var. JS Engine tarafından nasıl algılanıyor ve bu sırada prototype, __proto__ ve this gibi kavramları nasıl kullanıyor bunu örnekler üzerinden analiz edeceğiz.

Birinci Tür Kod Yazımı
Aşağıdaki örnekte 2 fonksiyon var. Bir tanesi user fonksiyonu return olarak obj dönüyor. diğeride sayHello fonksiyonu kendisine verilen user objesinin name alanını console basıyor.

İkinci Tür Kod Yazımı
sayHello fonksiyonun içerisine parametre geçirmesem diğer oluşturduğum obje üzerinden .sayHello ile bu fonksiyonu çağırabilsem. Bunu JS this ne anlama geliyor yazımda anlatmıştım. Obj kendi namespace oluşturup içerisinde yazdığımız fonksiyonlar o objeyi this olarak kullanarak this üzerinden o nesneye bağlı property değerlerine erişebilir.

Üçüncü Tür Kod Yazımı
Burada yaptığım obj oluşturma {} işlemi hiç de java’daki dil syntax benzemiyor. Acaba ben user fonksiyonun içerisindeki Object create etme ve return obj işleminden kendimi kurtarabilir miyim ?

Aşağıdaki resimde new operatörünün bu işlemi bizim yukarıda yaptığımız işlemi otomatik yaptığını return değerini ezmediğimiz sürece oluşturulan objeyi döndüğünü görebilirsiniz.

Dördüncü Tür Kod Yazımı
Bu kullanım güzel ama fonksiyonu new user() demeden de çağırabiliyoruz. Çünkü bu bir fonksiyon. Bunu java’daki kod syntax daha benzetsek class desek ve new kullanımına zorlayalım demişler. Eğer bir fonksiyon gibi new keyword kullanmadan çağırırsanız, aşağıdaki hatayı alırsınız.

TypeError: Class constructor user cannot be invoked without ‘new’

Dört Örnek İçin Arkaplan İncelemesi

1nci, 2nci, 3ncü durum için altyapılar aynı. hepside __proto__ Object üzerine kurulmuş yapıdalar. Yani kendilerinde bulunmayan bir fonksiyon örneğin toString fonksiyonu çağrıldığında bir üst Proto objesine bakılarak burada fonksiyon olduğu için o fonksiyon çağrılabilecektir.

sayHello fonksiyonu bağlandığı Context’ler birbirinden farklılık gösteriyor.

  • 1nci Durumda: Global Context Bağlı
  • 2nci ve 3ncü Durumda: Dönen Objenin Context’ine bağlı
  • 4ncü durumda ise: user class’ının prototype bağlı.
4 farklı durum için

Arka Plan Altyapılarını Nasıl Aynı Hale Getirebiliriz ?

Özetle biz 2nci ve 3ncü durumu class’dakine benzer bir hale getirmek isteseydik user fonksiyonun prototype bunu bağlamız gerekecekti.

2nci Durumda user fonksiyonun prototype oluşan objenin içerisine Object.create ile referans olarak verdiğimizde demek ki her user() ile oluşturduğumuz nesne içerisinde __proto__ ile kendisini oluşturan yapı referansını içerisinde taşıyacak.

Bu durumda fonksiyonunun oluşturacağı objelerde yapılabilecek fonksiyon templatelerini .prototype tutup yeni oluşan objelere kullanabilmeleri için bunu enjekte ediyor olmalı.

3ncü durum biz new kullandığımızda Object.create() sırasında yaptığımız prototype referansını alma işlemini arka planda otomatik olarak yapıyor.

.prototype vs __proto__ arasındaki Fark

Yukarıdaki örneklerden de göreceğiniz gibi fonksiyonlardan dönen Object, Array ve Object türeyen nesnelere ait .prototype yapısı içermezler çünkü bu ürettikleri nesneleri Object.create bunları kopyalamalarına gerek yoktur.

En basit örnekler ile anlatırsak bir object {} ve array [] oluşturduğunuzda bunların .prototype undefined ama __proto__ değerlerinin olduğunu görebilirsiniz ve proto değeri Array() ve Object() fonksiyonlarının .prototype nesnelerine eşit.

Object ve Array __proto__

Özetle __proto__ bizlere Prototype Chain üzerinde Extends etmiş object veya object yapılarının bir üst hiyerarşideki fonksiyonlarına erişmesini sağlayan kalıtımın (extends) çalışmasını sağlarken, .prototype bu objelerin __proto__ oluşturmasını sağlayan fonksiyon template oluşturmamıza yardımcı olur.

Referanslar

Okumaya Devam Et 😃

Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.

--

--