// Case A function Constructor() { this.foo = function() { ... }; ... } // vs // Case B function Constructor() { ... }; Constructor.prototype.foo = function() { ... } One of the main reasons people advise the use of prototypes is that .foo is created once in the case of the prototype where as this.foo is created multiple times when using the other approach.However one would expect interpreters can optimize this. So that there is only one copy of the function foo in case A.Of course you would still have a unique scope context for each object because of closures but that has less overhead then a new function for each object.Do modern JS interpreters optimise Case A so there is only one copy of the function foo ?
3 Réponses :
Oui, la création de fonctions utilise plus de mémoire.
... et, non, les interprètes ne optimisent pas la case une seule fonction. P>
La raison est La chaîne de la scorie JS nécessite chaque instance d'une fonction pour capturer les variables disponibles au moment de sa création. Cela dit, Les interprètes modernes sont Mozilla dit à Évitez les fermetures inutiles pour cette raison, Mais les fermetures sont l'un des outils les plus puissants et les plus utilisés dans une boîte à outils de JS Developer. P> Mise à jour: strong> il suffit de courir Ce test qui crée 1 million d'instances de constructeur, à l'aide de nœud.js (qui est v8, l'interprète JS en chrome). Avec et avec casea = true code> i Obtenir cette utilisation de la mémoire: p>
casea = false code> Je reçois cette utilisation de la mémoire: P>
{
rss: 73535488, //73 MB
vsize: 3149352960, //3149 MB
heapTotal: 74908960, //74 MB
heapUsed: 56308008 //56 MB
}
Pouvons-nous avoir des références qui définissent "mieux" et "interprètes modernes"
Vos tests correspondent à ce que j'ai trouvé dans la mienne aussi --- J'ai également ajouté des blocs de code volumineux à l'intérieur de la fonction pour tester si cela rendait le ballon de mémoire tout plus rapidement - et il n'a pas ... le code à l'intérieur de la fonction ne prend pas mémoire supplémentaire.
Oh - et j'ai également déconnecté une utilisation de la mémoire avant et après le test pour mesurer le diffusté avant la création d'objets
Peut-être la peine d'être vérifiée contre le chrome Canary V32 - on dirait qu'il y a eu des améliorations.
Les interprètes JavaScript ne sont pas l'optimisation des objets prototypes non plus. C'est simplement un cas de là en l'étant l'un d'entre eux par type (cette référence de plusieurs instances). Des constructeurs, d'autre part, créent de nouvelles instances et les méthodes définies dans elles. Donc, par définition, ce n'est vraiment pas un problème de «optimisation» d'interprétation, mais de simplement comprendre ce qui se passe. p>
sur une note latérale, si l'interprète devait essayer de consolider des méthodes d'instance, vous rencontreriez des problèmes si vous avez déjà décidé de modifier la valeur d'une dans une instance particulière (je préférerais que les maux de tête ne soient pas ajoutés à la langue) :) p>
Le compilateur optimise la fonction, elle n'oblige pas cependant le scopecontext.
Comment chaque interprète gère les doublons ne semble pas vraiment être la question cependant, l'interprète devra établir une différence entre plusieurs méthodes d'instance et cette différence consommera plus de mémoire.
Pour un cas, je m'attendrais à ce que un compilateur voit qu'il n'y a pas de variables locales dans le constructeur, il n'est donc pas nécessaire de garder son objet variable sur la chaîne d'étendue des instances. Si des variables locales sont utilisées, elle ne peut pas le faire, sauf si elle est suffisamment intelligente d'optimiser l'objet de variable si la fonction interne ne les réfère pas. Quoi qu'il en soit, j'utiliserais l'approche prototype comme son nitre et plus facilement maintenu (IMO bien sûr).
Je crois, après un bref test de noeud, que, dans les deux cas A et B, une copie du code réel pour la fonction Case A - Il existe un objet de fonction créé pour chaque exécution du constructeur Case B - Il n'y a qu'une seule portée, un objet de fonction, partagé via un prototype. P> foo code> en mémoire. P>
code> stockant une référence au code de fonctions et son champ d'exécution actuel. P>
Pouvez-vous poster votre code de test? Je suis sûr qu'il y a une certaine optimisation à l'intérieur de l'interprète pour éviter que analyse i> le code de fonction chaque fois, mais chaque passage à travers le constructeur doit capturer des références à toutes les variables en périmètre afin qu'elles puissent être correctement. résolu lorsque la fonction est invoquée.
@Broofa - Comparer mon code à la vôtre, c'est fondamentalement le même ... :) - Je viens de larguer comme 40 lignes de code de quelque chose d'autre dans la fonction pour tester cela ...