TLDR; No es súper necesario, pero probablemente ayudará a largo plazo, y es más preciso hacerlo.
NOTA: Mucho editado ya que mi respuesta anterior fue escrita de manera confusa y tenía algunos errores que no tuve en mi prisa por responder. Gracias a quienes señalaron algunos errores atroces.
Básicamente, es conectar subclases correctamente en Javascript. Cuando subclasemos, tenemos que hacer algunas cosas extrañas para asegurarnos de que la delegación prototípica funcione correctamente, incluida la sobrescritura de un prototypeobjeto. Sobrescribir un prototypeobjeto incluye el constructor, por lo que debemos corregir la referencia.
Veamos rápidamente cómo funcionan las 'clases' en ES5.
Digamos que tiene una función de constructor y su prototipo:
//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',
}
Cuando llame al constructor para crear una instancia, diga Adam:
// instantiate using the 'new' keyword
var adam = new Person('Adam', 19);
La newpalabra clave invocada con 'Persona' básicamente ejecutará el constructor Persona con algunas líneas de código adicionales:
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
* }
*/
Si nosotros console.log(adam.species), la búsqueda fallará en la adaminstancia, y buscamos la cadena prototípica en ella .prototype, que esPerson.prototype - y Person.prototype tiene una .speciespropiedad, por lo que la búsqueda tendrá éxito Person.prototype. Luego se registrará 'human'.
Aquí, el Person.prototype.constructorapuntará correctamente Person.
Así que ahora la parte interesante, la llamada 'subclase'. Si queremos crear una Studentclase, que es una subclase de la Personclase con algunos cambios adicionales, tendremos que asegurarnos de que Student.prototype.constructorapunta a Student para mayor precisión.
No hace esto por sí mismo. Cuando subclases, el código se ve así:
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: {}
Llamar new Student()aquí devolvería un objeto con todas las propiedades que queremos. Aquí, si lo comprobamos eve instanceof Person, volveríafalse . Si intentamos acceder eve.species, volvería undefined.
En otras palabras, necesitamos conectar la delegación para que eve instanceof Persondevuelva verdadero y para que las instancias de Studentdelegar correctamenteStudent.prototype , y luego Person.prototype.
PERO ya que lo estamos llamando con la newpalabra clave, ¿recuerda lo que agrega esa invocación? Llamaría Object.create(Student.prototype), que es cómo establecemos esa relación de delegación entre Studenty Student.prototype. Tenga en cuenta que en este momento, Student.prototypeestá vacío. Por lo tanto, buscar .speciesuna instancia de Studentfallará ya que solo delega Student.prototype, y el.species propiedad no existe en Student.prototype.
Cuando asignamos Student.prototypea sí mismo Object.create(Person.prototype), Student.prototypeluego delegamos a Person.prototype, y mirar hacia arriba eve.speciesregresará humancomo esperamos. Presumiblemente nos gustaría que herede de Student.prototype AND Person.prototype. Entonces necesitamos arreglar todo eso.
/* 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);
Ahora la delegación funciona, pero estamos sobrescribiendo Student.prototypecon una de Person.prototype. Entonces, si llamamos Student.prototype.constructor, apuntaría a en Personlugar de Student. Es por eso que necesitamos arreglarlo.
// 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
En ES5, nuestra constructorpropiedad es una referencia que se refiere a una función que hemos escrito con la intención de ser un 'constructor'. Aparte de lo que newnos da la palabra clave, el constructor es una función 'simple'.
En ES6, constructorahora está integrado en la forma en que escribimos clases, como en, se proporciona como un método cuando declaramos una clase. Esto es simplemente azúcar sintáctico, pero nos otorga algunas comodidades como el acceso a supercuando estamos ampliando una clase existente. Entonces escribiríamos el código anterior de esta manera:
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;
}
}