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ı, this
iç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 Person
nesne modeli oluşturmak istiyoruz . ancak bu adımda aynı şeyi prototype
ve new
anahtar kelimeyi kullanmadan yapmaya çalışacağım .
Yani bu aşamada functions
, objects
ve this
anahtar kelime, tek sahip bulunmaktadır.
İlk soru, anahtar kelime kullanmadan anahtar kelimenin nasıl this
yararlı 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 new
anahtar 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 window
tarayıcıdaki veya GLOBAL
iç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ş person
nesneyi değiştirmek , örneğin:
person.Person = Person;
person.getName = getName;
bu şekilde onlara şöyle diyebiliriz:
person.Person("George");
person.getName();// -->"George"
ve şimdi person
nesne şö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 person
nesnenin 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 Object
eklemek . Böylece yapabileceğinizden emin olmak için:propertiesObject
__proto__
console.log(person.__proto__===propertiesObject); //true
Ancak buradaki zor nokta __proto__
, person
nesnenin 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
, person
nesneye tam olarak işaret edilir .
c. JavaScript ile işlevini sağlamak için başka bir yol vardır this
kullanı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- new
Anahtar kelime nasıl çalışır?
Bu .prototype
iş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 new
kelime ve prototype
sen kullandığınızda, new
anahtar kelime. Bu nedenle, yaptığımız zaman new Person("George")
, Person
iş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_prototype
burada 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 getName
fonksiyonu ç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.prototype
nesnedir:
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 .prototype
ve ayrıca bu nesnenin kendi iç prototipi. ve bunun gibi.