JavaScript'te Nesne Prototipleri

0 Hisse senetleri
0
0
0
0

giriiş

 

Prototipler, JavaScript nesnelerinin birbirlerinden özellik devralma mekanizmasıdır. Bu makalede, prototipin ne olduğunu, prototip zincirlerinin nasıl çalıştığını ve bir nesne için prototipin nasıl ayarlanacağını açıklıyoruz.

Ön koşullar

JavaScript fonksiyonlarını anlayın, JavaScript temellerini (Başlarken ve Yapı Taşları bölümüne bakın) ve OOJS prensiplerini (Nesnelere Giriş bölümüne bakın) öğrenin.

Prototip zinciri

Tarayıcı konsolunda, bir sabit nesne oluşturmayı deneyin:

const myObject = {
city: "Madrid",
greet() {
console.log(`Greetings from ${this.city}`);
},
};
myObject.greet(); // Greetings from Madrid

Bu, tek bir veri özelliği (city) ve tek bir metodu (greet()) olan bir nesnedir. Konsola myObject gibi nesne adını ve ardından bir nokta işaretini yazarsanız, konsol bu nesne için kullanılabilen tüm özelliklerin bir listesini görüntüler. Şehir ve selamlamanın yanı sıra daha birçok özellik olduğunu göreceksiniz!

__defineGetter__
__defineSetter__
__lookupGetter__
__lookupSetter__
__proto__
city
constructor
greet
hasOwnProperty
isPrototypeOf
propertyIsEnumerable
toLocaleString
toString
valueOf

Bunlardan birine erişmeyi deneyin:

myObject.toString(); // "[object Object]"

Çalışıyor (toString()'in ne yaptığı tam olarak belli olmasa bile).

Peki bu ek özellikler nelerdir ve nereden geliyorlar?

JavaScript'teki her nesnenin prototip adı verilen yerleşik bir özelliği vardır. Prototip, kendi başına bir nesnedir, bu nedenle her prototipin kendi prototipi olur ve prototip zinciri adı verilen bir şey oluşturur. Bu zincir, prototipi null olan bir prototipe ulaştığımızda sona erer.

Not: Bir nesnenin prototipine işaret eden bir özelliğine prototip adı verilmez. Bu isim standart değildir, ancak pratikte tüm tarayıcılar __proto__ kullanır. Bir nesnenin prototipine erişmenin standart yolu Object.getPrototypeOf() metodudur.

 

Bir nesnenin bir özelliğine erişmeye çalıştığınızda: Özellik nesnenin kendisinde bulunmazsa, özelliğin prototipi aranır. Özellik hala bulunamazsa, örnek prototipi aranır ve özellik bulunana veya zincirin sonuna ulaşılana kadar bu şekilde devam edilir; bu durumda undefined döndürülür.

Bu yüzden myObject.toString()'i çağırdığımızda tarayıcı:

  • myObject'te toString'i arar
  • Orada bulamadım, bu yüzden toString için myObject nesne prototipine bakıyor
  • Orada bulur ve çağırır.

myObject'in prototipi nedir? Bunu öğrenmek için Object.getPrototypeOf() fonksiyonunu kullanabiliriz:

Object.getPrototypeOf(myObject); // Object { }

Bu, Object.prototype adlı bir nesnedir ve tüm nesnelerin varsayılan olarak sahip olduğu en temel prototiptir. Object.prototype prototipi null olduğundan, prototip zincirinin sonunda yer alır:

https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes/myobject-prototype-chain.svg

Bir nesnenin prototipi her zaman Object.prototype değildir. Şunu deneyin:

const myDate = new Date();
let object = myDate;
do {
object = Object.getPrototypeOf(object);
console.log(object);
} while (object);
// Date.prototype
// Object { }
// null

Bu kod bir Date nesnesi oluşturur, ardından prototip zincirinde yukarı doğru hareket eder ve prototipleri kaydeder. Bize myDate prototipinin bir Date.prototype nesnesi olduğunu ve prototipinin de Object.prototype olduğunu gösterir.

https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes/mydate-prototype-chain.svg

Aslında myDate2.getTime() gibi bilindik yöntemleri çağırdığınızda, Date.prototype'ta tanımlanmış bir yöntemi çağırıyorsunuz.

Gölgeleme özellikleri

Bir nesnenin prototipinde aynı ada sahip bir özellik tanımlandığında, nesne üzerinde bir özellik tanımlarsanız ne olur? Bakalım:

const myDate = new Date(1995, 11, 17);
console.log(myDate.getTime()); // 819129600000
myDate.getTime = function () {
console.log("something else!");
};
myDate.getTime(); // 'something else!'

Prototip zincirinin açıklaması göz önüne alındığında, bu tahmin edilebilir olmalıdır. getTime() işlevini çağırdığımızda, tarayıcı önce myDate içinde bu ada sahip bir özellik arar ve yalnızca myDate tanımlamıyorsa prototipi kontrol eder. Dolayısıyla, myDate'e getTime() işlevini eklediğimizde, myDate içindeki sürüm çağrılır.

Buna mülkün “gölgelenmesi” denir.

Bir prototip kurma

JavaScript'te bir nesnenin prototipini ayarlamanın birkaç yolu vardır ve burada ikisini açıklayacağız: Object.create() ve constructor.

Object.create'i kullanma

Object.create() metodu yeni bir nesne oluşturur ve yeni nesnenin prototipi olarak kullanılacak bir nesne belirtmenize olanak tanır.

İşte bir örnek:

const personPrototype = {
greet() {
console.log("hello!");
},
};
const carl = Object.create(personPrototype);
carl.greet(); // hello!

Burada, greet() metoduna sahip bir personPrototype nesnesi oluşturuyoruz. Ardından, prototipi personPrototype olan yeni bir nesne oluşturmak için Object.create() metodunu kullanıyoruz. Artık yeni nesne üzerinde greet()'i çağırabiliriz ve prototip, uygulamasını sağlayacaktır.

Oluşturucuyu kullanarak

JavaScript'te tüm fonksiyonların prototip adlı bir özelliği vardır. Bir fonksiyonu kurucu olarak çağırdığınızda, bu özellik yeni oluşturulan nesnenin prototipine ayarlanır (geleneksel olarak, __proto__ adlı bir özellikte).

Yani bir kurucunun prototipini belirlersek, o kurucuyla oluşturulan tüm nesnelere o prototipin verildiğinden emin olabiliriz:

const personPrototype = {
greet() {
console.log(`hello, my name is ${this.name}!`);
},
};
function Person(name) {
this.name = name;
}
Object.assign(Person.prototype, personPrototype);
// or
// Person.prototype.greet = personPrototype.greet;

Burada şunu yaratıyoruz:

  • greet() metoduna sahip bir personPrototype nesnesi
  • Oluşturulacak kişinin adını başlatan bir Person() constructor fonksiyonu.

Daha sonra personPrototype'da tanımlanan metotları Object.assign kullanarak Person fonksiyonunun prototype özelliğine koyuyoruz.

Bu koddan sonra Person.prototype() kullanılarak oluşturulan nesneler prototip olarak otomatik olarak greet metodunu alacaktır.

const reuben = new Person("Reuben");
reuben.greet(); // hello, my name is Reuben!

Bu aynı zamanda daha önce myDate prototipinin Date.prototype olarak adlandırılmasının nedenini de açıklıyor: Bu, Date oluşturucusunun prototype özelliğidir.

Kendi mülkü

Yukarıda Person constructor'ını kullanarak oluşturduğumuz nesnelerin iki özelliği vardır:

  • Kişi nesnelerinde doğrudan görünmesi için oluşturucuda ayarlanan bir ad özelliği
  • Prototipte ayarlanan bir greet() metodu.

Yöntemlerin prototipte, veri özelliklerinin ise oluşturucuda tanımlandığı bu kalıbı görmek yaygındır. Bunun nedeni, yöntemlerin genellikle oluşturduğumuz her nesne için aynı olması ve her nesnenin veri özellikleri için kendine özgü bir değere sahip olmasını istememizdir (burada her kişinin farklı bir adı olduğu gibi).

Burada name gibi doğrudan nesne üzerinde tanımlanan özelliklere kendi özellikleri denir ve bir özelliğin belirli bir özellik olup olmadığını statik Object.hasOwn() metodunu kullanarak kontrol edebilirsiniz:

const irma = new Person("Irma");
console.log(Object.hasOwn(irma, "name")); // true
console.log(Object.hasOwn(irma, "greet")); // false

Not: Burada statik olmayan Object.hasOwnProperty() metodunu da kullanabilirsiniz, ancak mümkünse Object.hasOwn() kullanmanızı öneririz.

Prototipler ve Kalıtım

Prototipler, kodun yeniden kullanılmasına ve nesne kompozisyonuna olanak tanıyan güçlü ve oldukça esnek bir JavaScript özelliğidir.

Özellikle kalıtımın bir versiyonunu desteklerler. Kalıtım, nesne yönelimli programlama dillerinin, programcıların bir sistemdeki bazı nesnelerin diğer nesnelerin daha özelleştirilmiş versiyonları olduğu fikrini ifade etmelerine olanak tanıyan bir özelliğidir.

Örneğin, bir okul modelliyorsak, öğretmenler ve öğrenciler olabilir: ikisi de insandır, bu nedenle bazı özellikleri paylaşırlar (örneğin, ikisinin de adı vardır), ancak her biri ek özellikler ekleyebilir (örneğin, öğretmenlerin öğrettiği bir konu vardır) veya aynı özelliği farklı şekillerde uygulayabilirler. Nesne yönelimli bir sistemde, öğretmenlerin ve öğrencilerin her ikisinin de İnsanlar'dan miras aldığını söyleyebiliriz.

JavaScript'te, Profesör ve Öğrenci nesnelerinin Kişi prototiplerine sahip olabildiklerinde, ortak özellikleri miras alabildiklerini, farklı olması gereken özellikleri ekleyip yeniden tanımlayabildiklerini görebilirsiniz.

Bir sonraki yazımızda nesne yönelimli programlama dillerinin diğer temel özellikleriyle birlikte kalıtım konusunu ele alacağız ve JavaScript'in bunları nasıl desteklediğini göreceğiz.

Sonuç

Bu makale, nesne prototip zincirlerinin nesnelerin birbirlerinden özellik devralmasına nasıl izin verdiği, prototip özelliği ve bunun oluşturuculara metot eklemek için nasıl kullanılacağı ve diğer ilgili konular dahil olmak üzere JavaScript nesne prototiplerini ele almaktadır.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Ayrıca Şunları da Beğenebilirsiniz