316 votes

Pourquoi est-il nécessaire de définir le prototype du constructeur?

Dans la Mozilla "Introduction à Javascript Objet de la section" à propos de l'Héritage (https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript#Inheritance), j'ai remarqué qu'ils définir le prototype.constructeur:

// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;  

Est-ce à servir un but important? Est-il possible de le supprimer?

279voto

lwburk Points 29313

Il n'est pas toujours nécessaire, mais il a ses utilise. Supposons que nous souhaitions faire une copie de la méthode sur la base Person classe. Comme ceci:

// define the Person Class  
function Person(name) {
    this.name = name;
}  

Person.prototype.copy = function() {  
    // return new Person(this.name); // just as bad
    return new this.constructor(this.name);
};  

// define the Student class  
function Student(name) {  
    this.name = name; 
}  

// inherit Person  
Student.prototype = new Person();  

Maintenant ce qui se passe lorsque nous créons un nouveau Student et les copier?

var student1 = new Student("trinth");  
console.log(student1.copy() instanceof Student); // => false

La copie n'est pas une instance d' Student. C'est parce que (sans explicite les vérifications), nous n'aurions aucun moyen pour revenir un Student copier à partir de la "base" de la classe. Nous ne pouvons que renvoyer un Person. Cependant, si nous aurions réinitialiser le constructeur:

// correct the constructor pointer because it points to Person  
Student.prototype.constructor = Student;

...ensuite, tout fonctionne comme prévu:

var student1 = new Student("trinth");  
console.log(student1.copy() instanceof Student); // => true

10voto

Stephen Points 3147

Je serais en désaccord. Il n'est pas nécessaire de définir le prototype. Prendre l'exacte même code, mais retirer le prototype.constructeur de la ligne. Ne rien changer? Pas de. Maintenant, apportez les modifications suivantes:

Person = function () {
    this.favoriteColor = 'black';
}

Student = function () {
    Person.call(this);
    this.favoriteColor = 'blue';
}

et à la fin de l'essai le code...

alert(student1.favoriteColor);

La couleur est bleu.

Un changement pour le prototype.constructeur, dans mon expérience, ne pas le faire, sauf si vous êtes en train de faire très spécifique, très compliqué les choses qui ne sont probablement pas une bonne pratique de toute façon :)

Edit: Après avoir farfouillé sur le web pour un peu et faire quelques essais, ça ressemble à des personnes définir le constructeur afin qu'il "regarde" comme la chose qui est en cours de construction avec les "nouveaux". Je suppose que je dirais que le problème c'est que javascript est un prototype de la langue - il n'y a pas une telle chose comme l'héritage. Mais la plupart des programmeurs qui viennent d'un milieu de programmation qui pousse l'héritage comme "le chemin". Nous arrivons donc avec toutes sortes de choses à essayer et à faire de ce prototype de la langue "classique" de la langue.. comme l'extension des "classes". Vraiment, dans l'exemple qu'ils ont donné, un nouvel élève est une personne - il n'est pas "étendre" à partir d'un autre étudiant.. l'étudiant est tout au sujet de la personne, et quelle que soit la personne est l'étudiant est ainsi. Étendre l'étudiant, et tout ce que vous avez prolongé est un étudiant au coeur, mais est personnalisé pour répondre à vos besoins.

Crockford est un peu fou et les excès de zèle, mais faire un peu de sérieux de lecture sur certaines des choses qu'il écrit.. il fera de vous regarder ce genre de choses très différemment.

9voto

James D Points 11

Cela a l'énorme piège que si vous avez écrit

Student.prototype.constructor = Student;

mais alors, si il y avait un Professeur dont le prototype a été également Personne et que vous avez écrit

Teacher.prototype.constructor = Teacher;

ensuite, l'Élève constructeur est maintenant Professeur!

Edit: Vous pouvez éviter cela en veillant à ce que vous aviez mis de l'Élève et l'Enseignant à l'aide de prototypes de nouvelles instances de la classe Personne créée à l'aide de l'Objet.créer, comme dans l'exemple Mozilla.

Student.prototype = Object.create(Person.prototype);
Teacher.prototype = Object.create(Person.prototype);

2voto

user3877965 Points 1

Obtenu un bon exemple de code d'pourquoi il est vraiment nécessaire de définir le prototype du constructeur..

function CarFactory(name){ 
   this.name=name;  
} 
CarFactory.prototype.CreateNewCar = function(){ 
    return new this.constructor("New Car "+ this.name); 
} 
CarFactory.prototype.toString=function(){ 
    return 'Car Factory ' + this.name;
} 

AudiFactory.prototype = new CarFactory();      // Here's where the inheritance occurs 
AudiFactory.prototype.constructor=AudiFactory;       // Otherwise instances of Audi would have a constructor of Car 

function AudiFactory(name){ 
    this.name=name;
} 

AudiFactory.prototype.toString=function(){ 
    return 'Audi Factory ' + this.name;
} 

var myAudiFactory = new AudiFactory('');
  alert('Hay your new ' + myAudiFactory + ' is ready.. Start Producing new audi cars !!! ');            

var newCar =  myAudiFactory.CreateNewCar(); // calls a method inherited from CarFactory 
alert(newCar); 

/*
Without resetting prototype constructor back to instance, new cars will not come from New Audi factory, Instead it will come from car factory ( base class )..   Dont we want our new car from Audi factory ???? 
*/

0voto

invisible bob Points 460

EDIT, en fait j'ai été mauvais. Commentant la ligne ne change pas c'est le comportement à tous. (Je l'ai testé)

Oui, c'est nécessaire. Lorsque vous ne

Student.prototype = new Person();  

Student.prototype.constructor devient Person. Par conséquent, appelant Student() serait de retour à un objet créé par Person. Ensuite, si vous ne

Student.prototype.constructor = Student; 

Student.prototype.constructor est réinitialisé pour Student. Maintenant, lorsque vous appelez Student() il exécute Student, ce qui appelle le constructeur parent Parent(), il renvoie l'correctement objet hérité. Si vous n'avez pas de réinitialisation Student.prototype.constructor avant de l'appeler, vous obtiendrez un objet qui n'aurait pas de l'un des biens mis en Student().

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X