web-dev-qa-db-fra.com

JavaScript: Class.method vs Class.prototype.method

Quelle est la différence entre les deux déclarations suivantes?

Class.method = function () { /* code */ }
Class.prototype.method = function () { /* code using this.values */ }

Peut-on 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?

476
postrational

Oui, la première fonction n'a pas de relation avec une instance d'objet de celle-ci fonction constructeur , vous pouvez la considérer comme une 'méthode statique' .

En JavaScript, les fonctions sont des objets de première classe , vous pouvez donc les traiter comme n'importe quel objet. Dans ce cas, vous ajoutez uniquement une propriété à le fonction function .

La seconde fonction, à mesure que vous développez le prototype de fonction constructeur, sera disponible pour toutes les instances d'objet créées avec le mot-clé new , ainsi que pour le contexte de cette fonction (le this = mot-clé) fera référence à l'instance d'objet réelle où vous l'appelez.

Considérons cet exemple:

// constructor function
function MyClass () {
  var privateVariable; // private member only available within the constructor fn

  this.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 instance
MyClass.staticMethod = function () {};

MyClass.prototype.publicMethod = function () {
  // the 'this' keyword refers to the object instance
  // you can access only 'privileged' and 'public' members
};

var myObj = new MyClass(); // new object instance

myObj.publicMethod();
MyClass.staticMethod();
674
CMS

Lorsque vous créez plusieurs instances de MyClass, vous n'avez toujours qu'une seule instance de publicMethod en mémoire, mais dans le cas de privilegedMethod, vous créez un grand nombre d'instances et staticMethod n'a pas de relation avec une instance d'objet.

C'est pourquoi les prototypes économisent de la mémoire.

De même, 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.

17
user2440156

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 = new ExampleClass();
someInstance.method('Called from instance');
    // >> error! `someInstance.method is not a function`  
_

Avec le même code, si .prototype est 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 = new ExampleClass();
someInstance.method('Called from instance');
                 // > output: `Called from instance`
_

Pour que ce soit plus clair,

_ExampleClass = function(){};
ExampleClass.directM = function(){}  //M for method
ExampleClass.prototype.protoM = function(){}

var instanceOfExample = new ExampleClass();

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é comme,
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 conservé cette séquence. ****

Résultats générés à partir de _chrome developer console_ & JS Bin
Cliquez sur le lien jsbin ci-dessus pour parcourir le code.
Basculer la section commentée avec ctrl+/

13
SAm

Oui, le premier est un static method également appelé class method, tandis que le second est un instance method.

Considérez les exemples suivants pour le comprendre plus en détail.

dans ES5

function Person(firstName, lastName) {
   this.firstName = firstName;
   this.lastName = lastName;
}

Person.isPerson = function(obj) {
   return obj.constructor === Person;
}

Person.prototype.sayHi = function() {
   return "Hi " + this.firstName;
}

Dans le code ci-dessus, isPerson est une méthode statique, tandis que sayHi est une méthode d'instance de Person.

Vous trouverez ci-dessous comment créer un objet à partir du constructeur Person.

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

class Person {
   constructor(firstName, lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
   }

   static isPerson(obj) {
      return obj.constructor === Person;
   }

   sayHi() {
      return `Hi ${this.firstName}`;
   }
}

Regardez comment static mot-clé a été utilisé pour déclarer la méthode statique isPerson.

Pour créer un objet de Person class.

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"

NOTE: Les deux exemples sont essentiellement les mêmes, JavaScript reste un langage sans classes. La class introduite dans ES6 est avant tout un sucre syntaxique par rapport au modèle d'héritage existant basé sur un prototype.

7
Aminu Kano