TLDR; Tidak super diperlukan, tetapi mungkin akan membantu dalam jangka panjang, dan lebih akurat untuk melakukannya.
CATATAN: Banyak yang diedit karena jawaban saya sebelumnya ditulis secara membingungkan dan memiliki beberapa kesalahan yang saya lewatkan saat terburu-buru untuk menjawab. Terima kasih kepada mereka yang menunjukkan beberapa kesalahan mengerikan.
Pada dasarnya, ini untuk mengirim subclass dengan benar di Javascript. Ketika kita subkelas, kita harus melakukan beberapa hal funky untuk memastikan bahwa delegasi prototipe berfungsi dengan benar, termasuk menimpa prototype
objek. Menimpa prototype
objek termasuk constructor
, jadi kita perlu memperbaiki referensi.
Mari kita cepat melihat bagaimana 'kelas' dalam ES5 bekerja.
Katakanlah Anda memiliki fungsi konstruktor dan prototipe:
//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',
}
Ketika Anda memanggil konstruktor untuk instantiate, katakan Adam
:
// instantiate using the 'new' keyword
var adam = new Person('Adam', 19);
Kata new
kunci yang dipanggil dengan 'Orang' pada dasarnya akan menjalankan konstruktor Orang dengan beberapa baris kode tambahan:
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
* }
*/
Jika kita console.log(adam.species)
, lookup akan gagal di adam
contoh, dan mencari rantai prototypal untuk nya .prototype
, yang Person.prototype
- dan Person.prototype
memiliki sebuah .species
properti, sehingga pencarian akan berhasil di Person.prototype
. Ini kemudian akan masuk'human'
.
Di sini, surat Person.prototype.constructor
wasiat akan menunjuk dengan benar Person
.
Jadi sekarang bagian yang menarik, yang disebut 'subclassing'. Jika kita ingin membuat Student
kelas, yaitu subkelas dari Person
kelas dengan beberapa perubahan tambahan, kita perlu memastikan bahwa Student.prototype.constructor
poin ke Siswa untuk akurasi.
Itu tidak melakukan ini dengan sendirinya. Saat Anda subkelas, kode ini terlihat seperti ini:
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: {}
Memanggil di new Student()
sini akan mengembalikan objek dengan semua properti yang kita inginkan. Di sini, jika kita periksa eve instanceof Person
, itu akan kembali false
. Jika kami mencoba mengakses eve.species
, itu akan kembaliundefined
.
Dengan kata lain, kita perlu mengirimkan delegasi sehingga eve instanceof Person
mengembalikan true dan agar instance Student
delegasi benar Student.prototype
, dan kemudian Person.prototype
.
TETAPI karena kami menyebutnya dengan new
kata kunci, ingat apa yang ditambahkan oleh doa itu? Itu akan memanggil Object.create(Student.prototype)
, yang bagaimana kita mengatur hubungan delegasi antara Student
dan Student.prototype
. Perhatikan bahwa saat ini, Student.prototype
kosong. Jadi mencari .species
contoh Student
akan gagal karena delegasi untuk hanya Student.prototype
, dan .species
properti tidak ada di Student.prototype
.
Ketika kita melakukan assign Student.prototype
untuk Object.create(Person.prototype)
, Student.prototype
dirinya kemudian delegasi untuk Person.prototype
, dan mencari eve.species
akan kembali human
seperti yang kita harapkan. Mungkin kita ingin mewarisi dari Student.prototype AND Person.prototype. Jadi kita harus memperbaiki semua itu.
/* 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);
Sekarang delegasi berfungsi, tetapi kami menimpa Student.prototype
dengan dari Person.prototype
. Jadi jika kita memanggil Student.prototype.constructor
, itu akan menunjuk ke Person
bukan Student
. Ini sebabnya kami harus memperbaikinya.
// 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
Di ES5, constructor
properti kami adalah referensi yang merujuk ke fungsi yang telah kami tulis dengan maksud untuk menjadi 'konstruktor'. Selain dari apanew
diberikan kata kunci kepada kami, konstruktor adalah fungsi 'polos'.
Dalam ES6, constructor
sekarang dibangun ke cara kita menulis kelas - seperti pada, itu disediakan sebagai metode ketika kita mendeklarasikan kelas. Ini hanyalah gula sintaksis tetapi itu memberi kita beberapa kenyamanan seperti akses ke super
ketika kita memperluas kelas yang ada. Jadi kita akan menulis kode di atas seperti ini:
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;
}
}