TLDR; Não é necessário, mas provavelmente ajudará a longo prazo, e é mais preciso fazê-lo.
OBSERVAÇÃO: Muito editada como minha resposta anterior foi confusa e tinha alguns erros que eu perdi na pressa em responder. Obrigado a quem apontou alguns erros flagrantes.
Basicamente, é para ligar subclasses corretamente em Javascript. Quando subclasses, temos que fazer algumas coisas descoladas para garantir que a delegação prototípica funcione corretamente, incluindo a substituição de um prototypeobjeto. A substituição de um prototypeobjeto inclui oconstructor , então precisamos corrigir a referência.
Vamos ver rapidamente como as 'classes' no ES5 funcionam.
Digamos que você tenha uma função construtora e seu protótipo:
//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',
}
Quando você chamar o construtor para instanciar, diga Adam:
// instantiate using the 'new' keyword
var adam = new Person('Adam', 19);
A newpalavra-chave invocada com 'Person' basicamente executará o construtor Person com algumas linhas de código adicionais:
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
* }
*/
Se nós console.log(adam.species), a pesquisa falharmos na adaminstância, e procurar a cadeia de protótipos na sua .prototype, que é Person.prototype- e Person.prototype tem uma .speciespropriedade, para que a pesquisa seja bem-sucedida Person.prototype. Em seguida, ele será registrado 'human'.
Aqui, o Person.prototype.constructorapontará corretamente para Person.
Então agora a parte interessante, a chamada 'subclasse'. Se queremos criar uma Studentturma, que é uma subclasse da Personturma com algumas alterações adicionais, precisamos garantir que os Student.prototype.constructorpontos apontem para precisão do aluno.
Não faz isso por si só. Quando você subclasse, o código fica assim:
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: {}
Ligar new Student()aqui retornaria um objeto com todas as propriedades que queremos. Aqui, se checarmos eve instanceof Person, ele retornaria false. Se tentarmos acessar eve.species, ele retornará undefined.
Em outras palavras, precisamos conectar a delegação para que eve instanceof Personretorne true e para que instâncias de Studentdelegar corretamente para Student.prototypee depois Person.prototype.
MAS, como a chamamos com a newpalavra - chave, lembre-se do que essa invocação adiciona? Isso chamaria Object.create(Student.prototype), e é assim que estabelecemos esse relacionamento delegacional entre Studente Student.prototype. Observe que, no momento, Student.prototypeestá vazio. Portanto, procurar .speciesuma instância de Studentfalharia, pois delega apenas Student.prototype , e a .speciespropriedade não existe Student.prototype.
Quando atribuímos Student.prototypea Object.create(Person.prototype), Student.prototypeele próprio delega e Person.prototype, olhando para cima eve.species, retornará humancomo esperamos. Presumivelmente, gostaríamos que herdasse do Student.prototype AND Person.prototype. Então, precisamos consertar tudo isso.
/* 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);
Agora a delegação funciona, mas estamos substituindo Student.prototypepor um de Person.prototype. Então, se ligarmos Student.prototype.constructor, apontaria para em Personvez de Student. Este é por isso que precisamos corrigi-lo.
// 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
No ES5, nossa constructorpropriedade é uma referência que se refere a uma função que escrevemos com a intenção de ser um 'construtor'. Além do que a newpalavra - chave nos fornece, o construtor é uma função "simples".
No ES6, o constructoragora está incorporado na maneira como escrevemos classes - como no, é fornecido como um método quando declaramos uma classe. Isso é simplesmente açúcar sintático, mas nos concede algumas conveniências, como o acesso a um superquando estamos estendendo uma classe existente. Então, escreveríamos o código acima dessa maneira:
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;
}
}