TLDR; Süper gerekli değildir, ancak muhtemelen uzun vadede yardımcı olacaktır ve bunu yapmak daha doğrudur.
NOT: Önceki cevabım kafa karıştırıcı bir şekilde yazılmış ve cevaplamak için acele ettiğim bazı hatalar olduğu için çok fazla düzenlenmişti. Bazı korkunç hatalara dikkat çekenlere teşekkürler.
Temel olarak, Javascript alt sınıflandırma doğru tel bağlamaktır. Alt sınıfa girdiğimizde, prototip delegasyonunun bir prototype
nesnenin üzerine yazılması da dahil olmak üzere düzgün çalıştığından emin olmak için bazı korkak şeyler yapmalıyız . Bir prototype
nesnenin üzerine yazmak constructor
, bu nedenle referansı düzeltmemiz gerekir.
ES5'teki 'sınıfların' nasıl çalıştığını hızlıca inceleyelim.
Diyelim ki bir yapıcı işleviniz ve onun prototipi var:
//Constructor Function
var Person = function(name, age) {
this.name = name;
this.age = age;
}
//Prototype Object - shared between all instances of Person
Person.prototype = {
species: 'human',
}
Kurucuyu somutlaştırmak için çağırdığınızda şunları söyleyin Adam
:
// instantiate using the 'new' keyword
var adam = new Person('Adam', 19);
new
'Kişi' ile çağrılan anahtar kelime temelde kod birkaç ek çizgilerle Kişi yapıcısı çalışacaktır:
function Person (name, age) {
// This additional line is automatically added by the keyword 'new'
// it sets up the relationship between the instance and the prototype object
// So that the instance will delegate to the Prototype object
this = Object.create(Person.prototype);
this.name = name;
this.age = age;
return this;
}
/* So 'adam' will be an object that looks like this:
* {
* name: 'Adam',
* age: 19
* }
*/
Biz ise console.log(adam.species)
, arama başarısız olur adam
mesela ve onun için prototypal zincirini bakmak .prototype
olduğunu Person.prototype
- ve Person.prototype
sahip bir .species
arama başarılı olur, böylece özelliği Person.prototype
. Daha sonra günlüğe kaydedilir 'human'
.
Burada, Person.prototype.constructor
doğru bir şekilde işaret edecektir Person
.
Şimdi ilginç kısım, sözde 'alt sınıflama'. Bir Student
sınıf oluşturmak istiyorsak , bu Person
bazı ek değişikliklerle sınıfın bir alt sınıfıdır, Student.prototype.constructor
doğruluk için Öğrenci'ye işaret ettiğinden emin olmamız gerekir .
Bunu tek başına yapmaz. Alt sınıf oluşturduğunuzda, kod şöyle görünür:
var Student = function(name, age, school) {
// Calls the 'super' class, as every student is an instance of a Person
Person.call(this, name, age);
// This is what makes the Student instances different
this.school = school
}
var eve = new Student('Eve', 20, 'UCSF');
console.log(Student.prototype); // this will be an empty object: {}
new Student()
Burada çağrı yapmak istediğimiz tüm özelliklere sahip bir nesne döndürür. Burada, kontrol edersek eve instanceof Person
, dönecekti false
. Eğer erişmeye çalışırsak eve.species
, geri dönecekti undefined
.
Başka bir deyişle, delege doğru şekilde eve instanceof Person
dönecek ve Student
delege örnekleri doğru bir şekilde Student.prototype
ve sonra olacak şekilde kablolamalıyız Person.prototype
.
AMA new
anahtar kelimeyle çağırdığımızdan , bu çağrının ne eklediğini hatırlıyor musunuz? Buna Object.create(Student.prototype)
, Student
ve arasındaki delegasyonel ilişkiyi böyle kurduk Student.prototype
. Şu anda Student.prototype
boş olduğunu unutmayın . Bu nedenle, .species
bir örneğini aramak yalnızcaStudent
temsilci seçerken başarısız olur ve mülk üzerinde mevcut değildir . Student.prototype
.species
Student.prototype
Biz atama yaptığımızda Student.prototype
için Object.create(Person.prototype)
, Student.prototype
için kendisi daha sonra delegelere Person.prototype
ve yukarı seyir eve.species
dönecektir human
beklediğimiz gibi. Muhtemelen Student.prototype AND Person.prototype'den miras almasını isteriz. Yani hepsini düzeltmemiz gerekiyor.
/* This sets up the prototypal delegation correctly
*so that if a lookup fails on Student.prototype, it would delegate to Person's .prototype
*This also allows us to add more things to Student.prototype
*that Person.prototype may not have
*So now a failed lookup on an instance of Student
*will first look at Student.prototype,
*and failing that, go to Person.prototype (and failing /that/, where do we think it'll go?)
*/
Student.prototype = Object.create(Person.prototype);
Şimdi delegasyon çalışıyor, ancak Student.prototype
bir ile yazıyoruz Person.prototype
. Eğer ararsak Student.prototype.constructor
, bunun Person
yerine işaret eder Student
. Bu yüzden düzeltmemiz gerekiyor.
// Now we fix what the .constructor property is pointing to
Student.prototype.constructor = Student
// If we check instanceof here
console.log(eve instanceof Person) // true
ES5'te, mülkümüz constructor
'yapıcı' olma niyetiyle yazdığımız bir işleve gönderme yapan bir referanstır. new
Anahtar kelimenin bize verdiklerinin yanı sıra , yapıcı aksi takdirde 'düz' bir işlevdir.
ES6'da, constructor
şimdi sınıf yazma şeklimizde yerleşiktir - olduğu gibi, bir sınıf ilan ettiğimizde bir yöntem olarak sağlanır. Bu sadece sözdizimsel şekerdir, ancak var super
olan bir sınıfı genişletirken bir zamana erişim gibi bazı kolaylıklar sağlıyor . Yani yukarıdaki kodu şöyle yazardık:
class Person {
// constructor function here
constructor(name, age) {
this.name = name;
this.age = age;
}
// static getter instead of a static property
static get species() {
return 'human';
}
}
class Student extends Person {
constructor(name, age, school) {
// calling the superclass constructor
super(name, age);
this.school = school;
}
}