146 votes

Déclaration de la méthode d'objet javascript dans la fonction constructeur par rapport au prototype

Dans la création d'objets en javascript, je peux mettre une déclaration de méthode dans le constructeur de la fonction ou dans le prototype. Par exemple, dire que je veux un Chien classe qui a un Nom de propriété et l'Écorce de la méthode. Je peux mettre de la déclaration de l'Écorce de la méthode dans le constructeur de la fonction:

var Dog = function(name) {
    this.Name = name;
    this.Bark = function() {
        alert(this.Name + " bark");
    };
}

ou je pourrais mettre comme une méthode sur l'objet prototype:

var Dog = function(name) {
    this.Name = name;
}

Dog.prototype.Bark = function() {
    alert(this.Name + " bark");
};

Quand je instancier des objets de type Chien, les deux approches semblent bien fonctionner:

var dog = new Dog("Fido");
dog.Bark();  //Both approaches show "Fido bark"

Dois-je préférer l'un de ces approches par rapport à l'autre? Existe-il des avantages à utiliser l'un plutôt que l'autre? En coulisses, ces deux approches finissez par faire exactement la même chose? L'approche de la plupart des gens ont tendance à favoriser?

Merci pour l'aide.

215voto

Tim Down Points 124501

Pour l'exemple que vous donnez, vous devez utiliser le prototype de l'approche. En général, ça dépend. Le principal avantage de la première approche (méthodes d'initialisation dans le constructeur), c'est que vous pouvez profiter de fermetures en rendant l'utilisation de variables locales définies dans le constructeur dans vos méthodes. Ces variables ne sont pas directement accessibles à l'extérieur de la fonction constructeur de la sorte sont en fait des "privé", ce qui signifie que votre API est plus propre que si ces variables ont été défini en tant que propriétés de l'objet. Quelques règles de base à respecter:

  • Si vos méthodes ne pas utiliser des variables locales définies dans votre constructeur (ton exemple ne marche pas), puis utilisez le prototype de l'approche.
  • Si vous êtes à la création d'un grand nombre de Dogs, utilisez le prototype de l'approche. De cette façon, tous les "instances" (c'est à dire les objets créés par l' Dog constructeur) vont se partager un ensemble de fonctions, alors que le constructeur façon, un nouvel ensemble de fonctions est créé à chaque fois que l' Dog constructeur est appelé, à l'aide de plus de mémoire.
  • Si vous êtes en train de créer un petit nombre d' Dogs et de trouver que l'utilisation de locaux, "privé", les variables dans votre constructeur améliore votre code, cela peut être la meilleure approche. Utilisez votre jugement et de faire quelques benchmarks si les performances ou la consommation de mémoire sont des préoccupations majeures.

Il est possible d'utiliser une approche hybride selon laquelle seules des méthodes qui en ont besoin l'accès aux locaux constructeur privé variables sont définies dans le constructeur, tandis que d'autres méthodes sont affectées au prototype.

Par exemple, le code ci-dessous utilise une variable locale dans le constructeur pour garder une trace du nombre de fois que ce chien a aboyé tout en gardant le nombre réel privé, de sorte que les aboiements des méthodes associées sont définis à l'intérieur du constructeur. La queue ne nécessite pas l'accès au nombre de barques, par conséquent, cette méthode peut être définie sur le prototype.

var Dog = function(name) {
    this.name = name;

    var barkCount = 0;

    this.bark = function() {
        barkCount++;
        alert(this.name + " bark");
    };

    this.getBarkCount = function() {
        alert(this.name + " has barked " + barkCount + " times");
    };
};

Dog.prototype.wagTail = function() {
    alert(this.name + " wagging tail");
};

var dog = new Dog("Dave");
dog.bark();
dog.bark();
dog.getBarkCount();
dog.wagTail();

11voto

Mathias Schwarz Points 4741

Les deux sont différents: dans Le premier on va stocker la référence à la méthode uniquement sur le prototype de l'objet alors que la deuxième solution va stocker la méthode sur chaque partie de l'objet. Cela signifie que chaque objet contient un pointeur supplémentaire et ainsi un peu plus la mémoire de chacun.

La méthode de l'objet permet à la méthode de référence à des variables dans le constructeur (à la fermeture) et il vous permet donc d'accéder à certaines données que vous ne pouvez pas accéder à partir d'un prototype méthodes.

Enfin, un prototype de méthode peut être changé par la suite, c'est que vous pouvez redéfinir Bark lors de l'exécution sur le prototype de l'objet, et ce changement sera le même pour tous les objets de ce prototype (puisque la méthode est toujours regardé de haut par le prototype).

9voto

jjm Points 1883

La grande majorité de code javascript que j'ai vu utilise la méthode de prototype. Je pense qu'il y a à cela trois raisons que je peux penser à du haut de ma tête.

La première est d'éviter d'avoir à chaque classe d'être un énorme constructeur: constructeur de logique dans la fonction constructeur, logique pour d'autres méthodes est déclarée ailleurs, c'est surtout une clarté chose / la séparation des préoccupations chose, mais en javascript dont vous avez besoin chaque peu de clarté, vous pouvez obtenir vos mains sur.

La deuxième est l'efficacité. Lorsque vous déclarez des méthodes dans le constructeur, vous créez une nouvelle instance de la fonction de l'objet pour chaque instance de l'objet, et aussi la liaison de la portée du constructeur pour chacune de ces fonctions (c'est-à-dire de référence, par exemple, les arguments du constructeur, qui peut ensuite être jamais gc avais aussi longtemps que l'objet de vies). Lorsque vous déclarez des méthodes sur le prototype il y a une seule copie de la fonction de l'objet qui est utilisé par toutes les instances--prototype propriétés ne sont pas copiés sur les instances.

Une troisième raison est que vous pouvez "sortir" d'une classe de différentes façons lorsque vous utilisez la méthode de prototype, comme le chaînage de prototype utilisé par Backbone.js et CoffeeScript la classe de construire.

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