Bu, açıklama sırasında henüz bir yorum yapılmadan örnek olarak kabul edilecek çok basit bir prototip tabanlı nesne modelidir:
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
console.log(this.name);
}
var person = new Person("George");
Prototip konseptine geçmeden önce dikkate almamız gereken bazı önemli noktalar vardır.
1- JavaScript işlevlerinin gerçekte nasıl çalıştığı:
İlk adımı atmak için, JavaScript işlevlerinin gerçekte nasıl çalıştığını, thisiçindeki anahtar kelimeyi kullanan bir sınıf gibi işlev veya bağımsız değişkenleriyle normal bir işlev olarak, ne yaptığını ve ne döndürdüğünü bulmamız gerekir.
Diyelim ki bir Personnesne modeli oluşturmak istiyoruz . ancak bu adımda aynı şeyi prototypeve newanahtar kelimeyi kullanmadan yapmaya çalışacağım .
Yani bu aşamada functions, objectsve thisanahtar kelime, tek sahip bulunmaktadır.
İlk soru, anahtar kelime kullanmadan anahtar kelimenin nasıl thisyararlı olabileceğidirnew .
Buna cevap vermek için boş bir nesnemiz olduğunu ve şöyle iki fonksiyonumuz olduğunu varsayalım:
var person = {};
function Person(name){ this.name = name; }
function getName(){
console.log(this.name);
}
ve şimdi kullanmadan newanahtar kelime biz bu işlevleri kullanabilirsiniz nasıl. Dolayısıyla JavaScript'in bunu yapmanın 3 farklı yolu vardır:
a. ilk yol, işlevi normal bir işlev olarak çağırmaktır:
Person("George");
getName();//would print the "George" in the console
bu durumda, bu genellikle windowtarayıcıdaki veya GLOBALiçindeki global nesne olan geçerli bağlam nesnesi olacaktır Node.js. Bu demektir ki, tarayıcıda window.name veya Node.js'de GLOBAL.name, değeri "George" olacaktı.
b. Biz yapabilirsiniz takmak onun özellikleri olarak, bir nesneye onları
- Bunu yapmanın en kolay yolu boş personnesneyi değiştirmek , örneğin:
person.Person = Person;
person.getName = getName;
bu şekilde onlara şöyle diyebiliriz:
person.Person("George");
person.getName();// -->"George"
ve şimdi personnesne şöyle:
Object {Person: function, getName: function, name: "George"}
- Bir nesneye bir özellik eklemek için diğer bir yolprototype , adı ile herhangi bir JavaScript nesnesinde bulunabilen bu nesnenin kullanarak __proto__, ve ben özet bölümünde biraz açıklamaya çalıştım. Böylece benzer sonucu elde edebiliriz:
person.__proto__.Person = Person;
person.__proto__.getName = getName;
Ancak bu şekilde yaptığımız şey şu şekilde değişiklik yapmaktır Object.prototype, çünkü değişmez değerler ( { ... }) kullanarak bir JavaScript nesnesi oluşturduğumuzda, buna dayalı olarak oluşturulur Object.prototype, yani yeni oluşturulan nesneye adlı bir öznitelik olarak eklenir __proto__, yani , önceki kod snippet'imizde yaptığımız gibi, tüm JavaScript nesneleri değişecekti, iyi bir uygulama değil. Peki şimdi daha iyi uygulama ne olabilir:
person.__proto__ = {
Person: Person,
getName: getName
};
ve şimdi diğer nesneler barış içinde, ama yine de iyi bir uygulama gibi görünmüyor. Bu yüzden hala bir çözümümüz daha var, ancak bu çözümü kullanmak için personnesnenin oluşturulduğu kod satırına geri dönmeliyiz ( var person = {};) ve sonra şu şekilde değiştirmeliyiz:
var propertiesObject = {
Person: Person,
getName: getName
};
var person = Object.create(propertiesObject);
yaptığı şey yeni bir JavaScript oluşturmak ve özelliğe Objecteklemek . Böylece yapabileceğinizden emin olmak için:propertiesObject__proto__
console.log(person.__proto__===propertiesObject); //true
Ancak buradaki zor nokta __proto__, personnesnenin ilk düzeyinde tanımlanan tüm özelliklere erişebilmenizdir (daha fazla ayrıntı için özet bölümünü okuyun).
Gördüğünüz gibi, bu iki yoldan herhangi biri kullanıldığında this, personnesneye tam olarak işaret edilir .
c. JavaScript ile işlevini sağlamak için başka bir yol vardır thiskullanıyor, çağrıyı veya uygulamak işlevini çağırmak için.
Apply () yöntemi, belirli bir değere sahip bir işlevi çağırır ve dizi (veya dizi benzeri bir nesne) olarak sağlanan bağımsız değişkenler.
ve
Call () yöntemi, verilen bu değere sahip bir işlevi ve bağımsız olarak sağlanan bağımsız değişkenleri çağırır.
bu şekilde benim favorim, fonksiyonlarımızı kolayca çağırabiliriz:
Person.call(person, "George");
veya
//apply is more useful when params count is not fixed
Person.apply(person, ["George"]);
getName.call(person);
getName.apply(person);
bu 3 yöntem .prototype işlevselliğini anlamak için önemli ilk adımlardır.
2- newAnahtar kelime nasıl çalışır?
Bu .prototypeişlevselliği anlamak için ikinci adımdır. bu süreci simüle etmek için kullandığım şey:
function Person(name){ this.name = name; }
my_person_prototype = { getName: function(){ console.log(this.name); } };
bu bölümünde ben de kullanmadan JavaScript alır tüm adımları atmaya çalışıyor olduğum newkelime ve prototypesen kullandığınızda, newanahtar kelime. Bu nedenle, yaptığımız zaman new Person("George"), Personişlev bir kurucu olarak işlev görür, Bunlar JavaScript'in yaptığı, birer birer:
a. her şeyden önce boş bir nesne, temelde boş bir karma yapar:
var newObject = {};
b. JavaScript'in atması gereken bir sonraki adım , tüm prototip nesnelerini yeni oluşturulan nesneye eklemektir
Elimizdeki my_person_prototypeburada prototip nesnesine benzer.
for(var key in my_person_prototype){
newObject[key] = my_person_prototype[key];
}
JavaScript'in aslında prototipte tanımlanan özellikleri eklemesi böyle değildir. Gerçek yol, prototip zinciri konseptiyle ilgilidir.
a. & b. Bu iki adım yerine, tam olarak aynı sonucu elde edebilirsiniz:
var newObject = Object.create(my_person_prototype);
//here you can check out the __proto__ attribute
console.log(newObject.__proto__ === my_person_prototype); //true
//and also check if you have access to your desired properties
console.log(typeof newObject.getName);//"function"
şimdi getNamefonksiyonu çağırabiliriz bizim my_person_prototype:
newObject.getName();
c. sonra bu nesneyi kurucuya verir,
biz bunu bizim örnek ile yapabilirsiniz:
Person.call(newObject, "George");
veya
Person.apply(newObject, ["George"]);
Daha sonra yapıcı, çünkü istediği her şeyi yapabilir , bu o yapıcı içinde yeni oluşturulan nesnedir.
şimdi diğer adımları simüle etmeden önceki sonuç: Object {name: "George"}
Özet:
Temel olarak, bir işlevde yeni anahtar sözcüğü kullandığınızda , bunu çağırırsınız ve bu işlev bir yapıcı işlevi görür, bu nedenle şunları söylediğinizde:
new FunctionName()
JavaScript dahili olarak bir nesne, boş bir karma yapar ve daha sonra bu nesneyi kurucuya verir, sonra kurucu istediği her şeyi yapabilir, çünkü bu kurucunun içindeki yeni oluşturulan nesne ve daha sonra size elbette o nesneyi verir return deyimini işlevinizde kullanmadıysanız veya return undefined;işlev gövdesinin sonuna bir koyduysanız .
Dolayısıyla JavaScript bir nesne üzerindeki bir özelliği aramaya gittiğinde, yaptığı ilk şey, o nesne üzerinde görünmesidir. Ve [[prototype]]genellikle sahip olduğumuz gizli bir özellik var __proto__ve bu özellik JavaScript'in bir sonraki bakışta olduğunu gösteriyor. Ve tekrar baktığında __proto__, yine başka bir JavaScript nesnesi olduğu zaman, kendi __proto__niteliği vardır, bir sonraki __proto__boş olana ulaşıncaya kadar yukarı ve yukarı gider . Nokta, JavaScript'te __proto__özelliğinin null olduğu tek Object.prototypenesnedir:
console.log(Object.prototype.__proto__===null);//true
JavaScript'te kalıtım bu şekilde çalışır.

Başka bir deyişle, bir işlev üzerinde bir prototip özelliğiniz olduğunda ve bunun üzerinde yeni bir çağrı yaptığınızda, JavaScript yeni özellikler için özellikler için bakmayı bitirdikten sonra, işlevin işlevlerine bakacaktır .prototypeve ayrıca bu nesnenin kendi iç prototipi. ve bunun gibi.