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 prototypeobjek. Menimpa prototypeobjek 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 newkunci 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 adamcontoh, dan mencari rantai prototypal untuk nya .prototype, yang Person.prototype- dan Person.prototype memiliki sebuah .speciesproperti, sehingga pencarian akan berhasil di Person.prototype. Ini kemudian akan masuk'human' .
Di sini, surat Person.prototype.constructorwasiat akan menunjuk dengan benar Person.
Jadi sekarang bagian yang menarik, yang disebut 'subclassing'. Jika kita ingin membuat Studentkelas, yaitu subkelas dari Personkelas dengan beberapa perubahan tambahan, kita perlu memastikan bahwa Student.prototype.constructorpoin 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 Personmengembalikan true dan agar instance Studentdelegasi benar Student.prototype, dan kemudian Person.prototype.
TETAPI karena kami menyebutnya dengan newkata kunci, ingat apa yang ditambahkan oleh doa itu? Itu akan memanggil Object.create(Student.prototype), yang bagaimana kita mengatur hubungan delegasi antara Studentdan Student.prototype. Perhatikan bahwa saat ini, Student.prototypekosong. Jadi mencari .speciescontoh Studentakan gagal karena delegasi untuk hanya Student.prototype , dan .speciesproperti tidak ada di Student.prototype.
Ketika kita melakukan assign Student.prototypeuntuk Object.create(Person.prototype), Student.prototypedirinya kemudian delegasi untuk Person.prototype, dan mencari eve.speciesakan kembali humanseperti 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.prototypedengan dari Person.prototype. Jadi jika kita memanggil Student.prototype.constructor, itu akan menunjuk ke Personbukan 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, constructorproperti 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, constructorsekarang 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 superketika 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;
}
}