JavaScript: Class.method vs Class.prototype.method
499
Quelle est la différence entre les deux déclarations suivantes?
Class.method =function(){/* code */}Class.prototype.method =function(){/* code using this.values */}
Est-il correct de considérer la première instruction comme une déclaration d'une méthode statique et la seconde comme une déclaration d'une méthode d'instance?
Oui, la première fonction n'a aucune relation avec une instance d'objet de cette fonction constructeur , vous pouvez la considérer comme une «méthode statique» .
En JavaScript, les fonctions sont des objets de première classe , ce qui signifie que vous pouvez les traiter comme n'importe quel objet, dans ce cas, vous n'ajoutez qu'une propriété à l' objet fonction .
La deuxième fonction, lorsque vous étendez le prototype de la fonction constructeur, il sera disponible pour toutes les instances d'objet créées avec le newmot - clé, et le contexte dans cette fonction (le thismot - clé) fera référence à l'instance d'objet réelle où vous l'appelez.
Considérez cet exemple:
// constructor functionfunctionMyClass(){var privateVariable;// private member only available within the constructor fnthis.privilegedMethod =function(){// it can access private members//..};}// A 'static method', it's just like a normal function // it has no relation with any 'MyClass' object instanceMyClass.staticMethod =function(){};MyClass.prototype.publicMethod =function(){// the 'this' keyword refers to the object instance// you can access only 'privileged' and 'public' members};var myObj =newMyClass();// new object instance
myObj.publicMethod();MyClass.staticMethod();
Mais pourquoi Function.prototype.method == Function.method?
Raghavendra
1
@Raghavendra ce n'est pas
Zorgatone
1
@Menda votre lien est mort
Eugen Sunic
19
Lorsque vous créez plusieurs instances de MyClass, vous n'aurez toujours qu'une seule instance de publicMethod en mémoire, mais en cas de privilegedMethod, vous finirez par créer de nombreuses instances et staticMethod n'a aucune relation avec une instance d'objet.
C'est pourquoi les prototypes économisent de la mémoire.
De plus, si vous modifiez les propriétés de l'objet parent, si la propriété correspondante de l'enfant n'a pas été modifiée, elle sera mise à jour.
Pour les apprenants visuels, lors de la définition de la fonction sans .prototype
ExampleClass=function(){};ExampleClass.method =function(customString){
console.log((customString !==undefined)?
customString :"called from func def.");}ExampleClass.method();// >> output: `called from func def.` var someInstance =newExampleClass();
someInstance.method('Called from instance');// >> error! `someInstance.method is not a function`
Avec le même code, si .prototypeest ajouté,
ExampleClass.prototype.method =function(customString){
console.log((customString !==undefined)?
customString :"called from func def.");}ExampleClass.method();// > error! `ExampleClass.method is not a function.` var someInstance =newExampleClass();
someInstance.method('Called from instance');// > output: `Called from instance`
Pour le rendre plus clair,
ExampleClass=function(){};ExampleClass.directM =function(){}//M for methodExampleClass.prototype.protoM =function(){}var instanceOfExample =newExampleClass();ExampleClass.directM();✓ works
instanceOfExample.directM(); x Error!ExampleClass.protoM(); x Error!
instanceOfExample.protoM();✓ works
**** Remarque pour l'exemple ci-dessus, someInstance.method () ne sera pas exécuté car,
ExampleClass.method () provoque une erreur et l'exécution ne peut pas continuer.
Mais pour des raisons d'illustration et de compréhension, j'ai gardé cette séquence. ****
Résultats générés à partir de chrome developer console&
Cliquez sur le lien jsbin ci-dessus pour parcourir le code.
Basculer la section commentée avec +JS Bin
Regardez comment le staticmot clé a été utilisé pour déclarer la méthode statique isPerson.
Créer un objet de Personclasse.
const aminu = new Person("Aminu", "Abubakar");
Utilisation de la méthode statique isPerson.
Person.isPerson(aminu); // will return true
Utilisation de la méthode d'instance sayHi.
aminu.sayHi(); // will return "Hi Aminu"
REMARQUE: les deux exemples sont essentiellement les mêmes, JavaScript reste un langage sans classe. Le classintroduit dans ES6 est principalement un sucre syntaxique sur le modèle d'héritage basé sur un prototype existant.
"Dans ES6", vous décrivez un sucre de syntaxe uniquement. Ce n'est pas la façon "ES2015" (s'il vous plaît tout le monde arrête d'utiliser ES6 d'utiliser le terme approprié ES2015). C'est simplement une autre façon de procéder et, à mon avis, la mauvaise façon.
K - La toxicité du SO augmente.
2
@KarlMorrison Aminu n'a pas écrit "façon de faire", vous l'avez écrit vous-même et vous y êtes opposé. Votre point peut être juste à propos de ES6 vs ES2015 mais dans la conversation, les gens ont souvent recours à une convention plus courte pour l'efficacité, donc je pense que le supprimer de l'écriture n'est pas possible ou certainement recommandé.
wuliwong
Merci pour la partie ES6 de votre réponse; cela clarifie beaucoup, surtout lorsqu'il est combiné avec les 2 réponses "public + privilégié" ci-dessus. Je suis cependant profondément confus par le obj.constructor === Personfait trueque vous soyez un exemple ... Whaaaat? Comment le constructeur d'une instance de classe peut-il créer ===la classe elle-même ...? (C'est comme dire qu'un sous-ensemble d'un ensemble est l'ensemble lui-même, etc ...)
Andrew
Ohhh ... est-ce que tout cela veut dire que littéralement, le constructeur est tout ce qu'une classe JS est vraiment à la fin de la journée? Tout le reste est soit empilé dans le constructeur, soit totalement une construction statique isolée de la classe, sauf par nom / concept (et comme un "ceci" implicite étant rendu évident)? (Ainsi, ce que je pensais être un sous-ensemble de l'ensemble n'était en fait pas un sous-ensemble.)
Lorsque vous créez plusieurs instances de MyClass, vous n'aurez toujours qu'une seule instance de publicMethod en mémoire, mais en cas de privilegedMethod, vous finirez par créer de nombreuses instances et staticMethod n'a aucune relation avec une instance d'objet.
C'est pourquoi les prototypes économisent de la mémoire.
De plus, si vous modifiez les propriétés de l'objet parent, si la propriété correspondante de l'enfant n'a pas été modifiée, elle sera mise à jour.
la source
Pour les apprenants visuels, lors de la définition de la fonction sans
.prototype
Avec le même code, si
.prototype
est ajouté,Pour le rendre plus clair,
**** Remarque pour l'exemple ci-dessus, someInstance.method () ne sera pas exécuté car,
ExampleClass.method () provoque une erreur et l'exécution ne peut pas continuer.
Mais pour des raisons d'illustration et de compréhension, j'ai gardé cette séquence. ****
Résultats générés à partir de
chrome developer console
& Cliquez sur le lien jsbin ci-dessus pour parcourir le code. Basculer la section commentée avec +JS Bin
ctrl/
la source
Oui, le premier est
static method
également appeléclass method
, tandis que le second est uninstance method
.Considérez les exemples suivants, pour le comprendre plus en détail.
Dans ES5
Dans le code ci-dessus,
isPerson
est une méthode statique, tandis quesayHi
est une méthode d'instance dePerson
.Ci-dessous, comment créer un objet à partir du
Person
constructeur.var aminu = new Person("Aminu", "Abubakar");
Utilisation de la méthode statique
isPerson
.Person.isPerson(aminu); // will return true
Utilisation de la méthode d'instance
sayHi
.aminu.sayHi(); // will return "Hi Aminu"
Dans ES6
Regardez comment le
static
mot clé a été utilisé pour déclarer la méthode statiqueisPerson
.Créer un objet de
Person
classe.const aminu = new Person("Aminu", "Abubakar");
Utilisation de la méthode statique
isPerson
.Person.isPerson(aminu); // will return true
Utilisation de la méthode d'instance
sayHi
.aminu.sayHi(); // will return "Hi Aminu"
REMARQUE: les deux exemples sont essentiellement les mêmes, JavaScript reste un langage sans classe. Le
class
introduit dans ES6 est principalement un sucre syntaxique sur le modèle d'héritage basé sur un prototype existant.la source
obj.constructor === Person
faittrue
que vous soyez un exemple ... Whaaaat? Comment le constructeur d'une instance de classe peut-il créer===
la classe elle-même ...? (C'est comme dire qu'un sous-ensemble d'un ensemble est l'ensemble lui-même, etc ...)