Avantages de l'utilisation du prototype, vs méthodes de définition directe dans le constructeur? [dupliquer]

cette question a déjà une réponse ici:

je me demande s'il y a des avantages à utiliser l'un de ceux-ci par rapport à l'autre, et par Où dois-je aller?

approche constructeur:

var Class = function () {

    this.calc = function (a, b) {
        return a + b;
    };

};

Prototype approche:

var Class = function () {};

Class.prototype.calc = function (a, b) {
    return a + b;
};

Je n'aime pas cela, en utilisant le prototype, les définitions de méthode sont séparées de la classe, et je ne sais pas s'il y a une raison spécifique que je devrais utiliser cette plus que la première approche.

aussi, y a-t-il un avantage à utiliser une fonction littérale pour définir une "classe", au-dessus de juste définition de la fonction:

var Class = function () {};

vs

function Class () {};

Merci!

264
demandé sur Leo 2010-12-22 13:40:20

4 réponses

les méthodes héritées via la chaîne prototype peuvent être modifiées universellement pour toutes les instances, par exemple:

function Class () {}
Class.prototype.calc = function (a, b) {
    return a + b;
}

// Create 2 instances:
var ins1 = new Class(),
    ins2 = new Class();

// Test the calc method:
console.log(ins1.calc(1,1), ins2.calc(1,1));
// -> 2, 2

// Change the prototype method
Class.prototype.calc = function () {
    var args = Array.prototype.slice.apply(arguments),
        res = 0, c;

    while (c = args.shift())
        res += c;

    return res; 
}

// Test the calc method:
console.log(ins1.calc(1,1,1), ins2.calc(1,1,1));
// -> 3, 3

Avis Comment la modification de la méthode appliquée aux deux cas? C'est parce que ins1 et ins2 partagent la même fonction calc() . Pour faire cela avec des méthodes publiques créées pendant la construction, vous devez assigner la nouvelle méthode à chaque instance qui a été créée, ce qui est une tâche difficile. C'est parce que ins1 et ins2 auraient leurs propres fonctions, créées individuellement calc() .

un autre effet secondaire de la création de méthodes à l'intérieur du constructeur est une moins bonne performance. Chaque méthode doit être créée à chaque fois que la fonction constructeur tourne. Les méthodes sur la chaîne prototype sont créées une fois puis "héritées" par chaque instance. D'un autre côté, les méthodes publiques ont accès à des variables "privées", ce qui n'est pas possible avec les méthode.

quant à votre question function Class() {} vs var Class = function () {} , la première est "hissée" au sommet de la portée actuelle avant l'exécution. Pour ces derniers, la déclaration variable est hissée, mais pas la cession. Par exemple:

// Error, fn is called before the function is assigned!
fn();
var fn = function () { alert("test!"); } 

// Works as expected: the fn2 declaration is hoisted above the call
fn2();
function fn2() { alert("test!"); }
406
répondu Andy E 2010-12-22 11:23:19

L'avantage de l'approche par prototype est l'efficacité. Il y a un objet de fonction calc() partagé entre tous les objets Class (par lequel j'entends les objets créés en appelant le constructeur Class ). L'autre manière (assigner des méthodes au sein du constructeur) crée un nouvel objet de fonction pour chaque objet Class , en utilisant plus de mémoire et en prenant plus de temps de traitement lors de l'appel du constructeur Class . Cependant, cette approche a un avantage: l' La méthode calc() a accès à des variables locales au sein du constructeur, que vous pouvez utiliser à votre avantage:

function Class() {
    var calcCallCount = 0;

    this.calc = function (a, b) {
        ++calcCallCount;
        alert("Calc called " + calcCallCount + " times");
        return a + b;
    };
};

en ce qui concerne var Class = function() {...} versus function Class() {...} , je préfère généralement ce dernier est parce qu'il signifie que la fonction a un nom, qui peut être utile lors du débogage. L'autre différence est que cette dernière version (une déclaration de fonction ) est hissée, ce qui signifie qu'elle est disponible partout dans le domaine dans lequel elle est défini, pas seulement après la définition. Cependant, certaines personnes préfèrent utiliser le premier (une expression de fonction ) partout.

59
répondu Tim Down 2015-02-10 11:37:28
var YourClass = function(){
  var privateField = "somevalue";
  this.publicField = "somevalue";
  this.instanceMethod1 = function(){
     //you may access both private and public field from here:
     //in order to access public field, you must use "this":
     alert(privateField + "; " + this.publicField);
  };
}

YourClass.prototype.instanceMethod2 = function(){
  //you may access only public field 2 from this method, but not private fields:
  alert(this.publicField);
  //error: drawaback of prototype methods:
  alert(privateField);  
};

avantages des méthodes prototypes:

  1. lorsque vous définissez des méthodes via prototype, elles sont partagées entre toutes les instances de YourClass. En conséquence la taille totale de telles instances est < que si vous définissez des méthodes dans le constructeur; il y a des tests qui montrent comment la définition de méthode via prototype diminue la taille totale de la page html et en conséquence une vitesse de son chargement.

  2. un autre avantage des méthodes, définies via prototype - est que lorsque vous utilisez des classes héritées, vous pouvez outrepasser ces méthodes et dans la méthode overriden de la classe dérivée vous pouvez invoquer la méthode de la classe de base avec le même nom, mais avec des méthodes définies dans le constructeur, vous ne pouvez pas faire cela.

39
répondu Alexandr 2011-03-28 21:03:28

tout d'Abord, vous devez utiliser l'objet littéral comme ceci:

var Class = {
  calc: function (a, b) {
    return a + b;
  }
};

cette notation est plus propre et rend aussi évident que dans Javascript les objets ne sont que des hachures pas quelque chose d'une recette, comme une classe prédéfinie.

la différence entre les définitions est que si vous ajoutez une méthode au prototype il n'y aura qu'une seule méthode créée en mémoire pour toutes les instances. Donc, si vous avez une méthode générique et d'un objet qui est créé / utilisé dans plusieurs instances, vous devriez ajouter la méthode au prototype.

-4
répondu azAttis 2010-12-22 10:55:13