Je suis nouveau sur JavaScript OOP. Pouvez-vous s'il vous plaît expliquer la différence entre les blocs de code suivants? J'ai testé et les deux blocs fonctionnent. Quelle est la meilleure pratique et pourquoi?
Premier bloc:
function Car(name){
this.Name = name;
}
Car.prototype.Drive = function(){
console.log("My name is " + this.Name + " and I'm driving.");
}
SuperCar.prototype = new Car();
SuperCar.prototype.constructor = SuperCar;
function SuperCar(name){
Car.call(this, name);
}
SuperCar.prototype.Fly = function(){
console.log("My name is " + this.Name + " and I'm flying!");
}
var myCar = new Car("Car");
myCar.Drive();
var mySuperCar = new SuperCar("SuperCar");
mySuperCar.Drive();
mySuperCar.Fly();
Deuxième bloc:
function Car(name){
this.Name = name;
this.Drive = function(){
console.log("My name is " + this.Name + " and I'm driving.");
}
}
SuperCar.prototype = new Car();
function SuperCar(name){
Car.call(this, name);
this.Fly = function(){
console.log("My name is " + this.Name + " and I'm flying!");
}
}
var myCar = new Car("Car");
myCar.Drive();
var mySuperCar = new SuperCar("SuperCar");
mySuperCar.Drive();
mySuperCar.Fly();
Pourquoi l'auteur a-t-il ajouté les méthodes Drive
et Fly
à l'aide de prototype
et ne les a-t-il pas déclarées comme méthode this.Drive
dans la classe Car
et comme this.Fly
dans la classe SuperCar
Pourquoi SuperCar.prototype.constructor
doit-il être remis à SuperCar
? La propriété constructor
est-elle remplacée lorsque prototype
est défini? J'ai commenté cette ligne et rien n'a changé.
Pourquoi appeler Car.call(this, name);
dans le constructeur SuperCar
? Les propriétés et méthodes de Car
ne seront-elles pas 'héritées' quand je le ferai
var myCar = new Car("Car");
Les deux blocs diffèrent de manière à ce que, dans le premier exemple, Drive()
n'existe qu'une seule fois, alors que, dans la deuxième approche, Drive()
existera par instance (chaque fois que vous ferez new Car()
, la fonction drive()
sera créée à nouveau). Ou différents ont dit le premier utilise le prototype pour stocker la fonction et le second le constructeur. La recherche de fonctions est constructeur puis prototype. Donc, pour votre recherche de Drive()
, il le trouve, qu’il soit dans le constructeur ou dans le prototype. L'utilisation du prototype est plus efficace car vous n'avez généralement besoin d'une fonction qu'une fois par type.
L'appel new
en javascript définit automatiquement le constructeur dans le prototype. Si vous écrasez le prototype, vous devez donc définir le constructeur manuellement.
L'héritage javascript n'a rien à voir avec super
. Donc, si vous avez une sous-classe, la seule chance d'appeler le super constructeur est par son nom.
Pour ajouter à la réponse de Norbert Hartl , SuperCar.prototype.constructor n'est pas nécessaire, mais certaines personnes l'utilisent comme moyen pratique d'obtenir la fonction de construction d'un objet (les objets SuperCar dans ce cas).
Juste du premier exemple, Car.call (this, name) est dans la fonction constructeur SuperCar parce que, lorsque vous faites cela:
var mySuperCar = new SuperCar("SuperCar");
C'est ce que fait JavaScript:
Remarquez comment JavaScript n'a pas appelé Car pour vous. Les prototypes étant tels qu’ils sont, toute propriété ou méthode que vous ne définissez pas vous-même pour SuperCar sera recherchée dans Car. Parfois, c'est bon, par exemple SuperCar n'a pas de méthode Drive, mais il peut partager celle de Car. Tous les SuperCars utiliseront donc la même méthode. D'autres fois, vous ne voulez pas partager, comme chaque SuperCar ayant son propre nom. Alors, comment peut-on définir le nom de chaque SuperCar comme il se doit? Vous pouvez définir this.Name dans la fonction constructeur SuperCar:
function SuperCar(name){
this.Name = name;
}
Cela fonctionne, mais attendez une seconde. N'avons-nous pas fait exactement la même chose dans le constructeur automobile? Je ne veux pas nous répéter. Puisque Car définit déjà le nom, appelons-le simplement.
function SuperCar(name){
this = Car(name);
}
Oups, vous ne voulez jamais changer la référence d'objet this
spéciale. Rappelez-vous les 4 étapes? Accrochez-vous à cet objet que JavaScript vous a fourni, car c’est le seul moyen de conserver le précieux lien de prototype interne entre votre objet SuperCar et la voiture. Alors, comment pouvons-nous définir Name, sans nous répéter et sans jeter notre nouvel objet SuperCar? JavaScript a consacré tant d’efforts particuliers à nous préparer?
Deux choses. Un: la signification de this
est flexible. Deux: la voiture est une fonction. Il est possible d'appeler Car, non pas avec un objet instancié frais et vierge, mais plutôt avec, par exemple, un objet SuperCar. Cela nous donne la solution finale, qui fait partie du premier exemple de votre question:
function SuperCar(name){
Car.call(this, name);
}
En tant que fonction, il est autorisé d'appeler Car avec la méthode call de la fonction , qui modifie la signification de this
dans Car en l'instance SuperCar que nous construisons. Presto! Désormais, chaque SuperCar reçoit sa propre propriété Name.
Pour conclure, Car.call(this, name)
dans le constructeur SuperCar attribue à chaque nouvel objet SuperCar sa propre propriété Name unique, mais sans dupliquer le code déjà présent dans Car.
Les prototypes ne sont pas effrayants une fois que vous les comprenez, mais ils ne ressemblent pas du tout au modèle classique classe/héritage OOP. J'ai écrit un article sur le concept de prototypes en JavaScript . Il est écrit pour un moteur de jeu qui utilise JavaScript, mais c'est le même moteur JavaScript que celui utilisé par Firefox, donc tout devrait être pertinent. J'espère que cela t'aides.
Norbert, vous devriez noter que votre premier exemple est à peu près ce que Douglas Crockford appelle l'héritage pseudoclassique. Quelque chose à noter à ce sujet:
Enfin, je voudrais mentionner que j'ai plusieurs exemples de code d'héritage JavaScript de TDD qui fonctionne ici: Code et essai d'héritage de TDD JavaScript J'aimerais recevoir vos commentaires car j'espère pouvoir l'améliorer et le conserver. il open source. L'objectif est d'aider les programmeurs classiques à se familiariser rapidement avec JavaScript et à compléter l'étude des livres de Crockford et Zakas.
function abc() {
}
Méthodes de prototype et propriété créées pour la fonction abc
abc.prototype.testProperty = 'Hi, I am prototype property';
abc.prototype.testMethod = function() {
alert('Hi i am prototype method')
}
Création de nouvelles instances pour la fonction abc
var objx = new abc();
console.log(objx.testProperty); // will display Hi, I am prototype property
objx.testMethod();// alert Hi i am prototype method
var objy = new abc();
console.log(objy.testProperty); //will display Hi, I am prototype property
objy.testProperty = Hi, I am over-ridden prototype property
console.log(objy.testProperty); //will display Hi, I am over-ridden prototype property
http://astutejs.blogspot.in/2015/10/javascript-prototype-is-easy.html
Je ne suis pas sûr à 100%, mais je pense que la différence est que le deuxième exemple duplique simplement le contenu de la classe Car dans l'objet SuperCar, tandis que le premier lie le prototype SuperCar à la classe Car, de sorte que l'exécution change La classe voiture affecte également la classe SuperCar.