43 votes

Modèle de constructeur Javascript OO: néo-classique vs prototypal

J'ai regardé d'un discours de Douglas Crockford sur les bonnes pièces en Javascript et mes yeux ont été ouverts. A un moment, il dit quelque chose comme, "Javascript est la seule langue où les bons programmeurs pensent qu'ils peuvent l'utiliser de façon efficace, sans l'apprendre." Puis j'ai réalisé, je suis ce gars-là.

Dans son discours, il a fait des déclarations qui pour moi, ont été assez surprenant et perspicace. Par exemple, le JavaScript est le plus important de la programmation de langue sur la planète. Ou il est le plus populaire de langue sur la planète. Et, qu'il est divisé en de nombreuses façons sérieuses.

Le plus surprenant déclaration qu'il a faite, pour moi, c'était "nouveau, c'est dangereux". Il ne l'utilise pas plus. Il n'est pas utiliser this soit.

Il a présenté un modèle intéressant pour un constructeur en Javascript, qui permet privé et public des variables membres et s'appuie sur le ni newni this. Il ressemble à ceci:

// neo-classical constructor
var container =  function(initialParam) {
    var instance = {}; // empty object 

    // private members
    var privateField_Value = 0;
    var privateField_Name = "default";

    var privateMethod_M1 = function (a,b,c) {
        // arbitrary
    }; 

    // initialParam is optional
    if (typeof initialParam !== "undefined") {
        privateField_Name= initialParam;
    }

    // public members
    instance.publicMethod = function(a, b, c) {
        // because of closures,
        // can call private methods or
        // access private fields here. 
    };

    instance.setValue = function(v) {
        privateField_Value = v;
    };

    instance.toString = function(){
        return "container(v='" + privateField_Value + "', n='" + privateField_Name + "')";
    };

    return instance;
}


// usage
var a = container("Wallaby");
WScript.echo(a.toString()); 
a.setValue(42);
WScript.echo(a.toString()); 

var b = container();
WScript.echo(b.toString());

EDIT: le code mis à jour pour passer en minuscules nom de la classe.

Ce modèle a évolué à partir de Crockford antérieure de l'utilisation de modèles.

Question: utilisez-vous ce genre de constructeur modèle? Trouvez-vous qu'il compréhensible? Avez-vous une meilleure?

16voto

James Points 56229

Cela ressemble à de la non-singleton version du module de modèle, dans lequel les variables privées peut être simulé en prenant avantage de JavaScript "fermetures".

Je l'aime (un peu...). Mais je ne vois pas vraiment l'avantage de variables privées fait de cette façon, surtout quand cela signifie que toutes les nouvelles méthodes ajoutée (après initialisation) n'ont pas accès aux variables privées.

De Plus, il ne prend pas avantage de JavaScript prototypes modèle. Toutes vos méthodes et les propriétés doivent être initialisées à CHAQUE fois que le constructeur est appelé - cela ne se produit pas si vous avez des méthodes stockées dans le prototype du constructeur. Le fait est que, à l'aide des constructeur/prototype de modèle est beaucoup plus rapide! Pensez-vous vraiment les variables privées font l'impact sur les performances en vaut la peine?

Ce type de modèle fait sens avec le module de modèle parce que c'est seulement être initialisé qu'une seule fois (pour créer une pseudo-singleton), mais je n'en suis pas si sûr que ça a du sens ici.

Utilisez-vous ce genre de constructeur modèle?

Non, bien que je ne l'utilisation de son singleton variante, le module de modèle...

Trouvez-vous qu'il compréhensible?

Oui, c'est lisible et très clair, mais je n'aime pas l'idée de regrouper tout ce qui a à l'intérieur d'un constructeur comme ça.

Avez-vous une meilleure?

Si vous avez vraiment besoin de variables privées, puis coller avec elle par tous les moyens. Sinon il suffit d'utiliser les classiques constructeur/prototype de modèle (sauf si vous partagez Crockford, la peur de l' new/this combo):

function Constructor(foo) {
    this.foo = foo;
    // ...
}

Constructor.prototype.method = function() { };

D'autres questions similaires concernant Doug points de vue sur le sujet:

10voto

Caleb Points 2889

- Je éviter ce schéma que la plupart des gens trouvent qu'il est plus difficile à lire. J'ai suivent généralement deux approches:

  1. Si j'ai seulement un de quelque chose, puis-je utiliser des objets anonymes:

    var MyObject = {
        myMethod: function() {
            // do something
        }
    };
    
  2. Pour plus d'un, de quelque chose que j'utilise javascript standard prototypes héritage

    var MyClass = function() {
    };
    MyClass.prototype.myMethod = function() {
        // do something
    };
    
    
    var myObject = new MyClass();
    

(1) est beaucoup plus facile à lire, à comprendre et à écrire. (2) est plus efficace lorsqu'il y a plusieurs objets. Crockford du code va créer une nouvelle copie de fonctions à l'intérieur du constructeur de tous les temps. Fermeture a aussi l'inconvénient d'être plus difficile à déboguer.

Même si vous perdez vraiment des variables privées, vous préfixe censé être privé des membres avec _ comme une convention.

this est certes difficile problème en javascript, mais peut être contourné en utilisant .call et .apply pour le configurer correctement. J'ai aussi souvent utiliser var self = this; pour créer une fermeture variable pour l'utiliser comme this à l'intérieur des fonctions définies à l'intérieur d'une fonction membre.

MyClass.prototype.myMethod = function() {
    var self = this;

    // Either
    function inner1() {
        this.member();
    }
    inner1.call(this);

    // Or
    function inner2() {
        self.member();
    }
    inner2();
};

7voto

Justin Johnson Points 16243

Utilisez-vous ce genre de constructeur modèle?

Nope

Trouvez-vous qu'il compréhensible?

Oui, c'est très simple.

Avez-vous une meilleure?

Je n'ai pas vu de parler encore, mais je reviendrai bientôt. Jusqu'alors, je ne vois pas le danger de l'utilisation de new et this, et voici pourquoi:

Sans en avoir entendu ses points, je ne peux que supposer qu'il suggère de rester loin de ces choses à cause de la nature de l' this, et la façon dont elle est sujette à modification en fonction du contexte dans lequel une méthode particulière est exécutée (directement sur l'objet d'origine ou comme un rappel, etc). En tant qu'éducateur, il est peut-être l'enseignement de l'évitement de ces mots-clés en raison de la situation démographique en grande partie inconscient et l'inexpérience des développeurs qui se souillent en JavaScript sans d'abord grokking la nature de la langue. Pour les développeurs expérimentés qui sont intimement connaissance avec la langue, je ne suis pas convaincu qu'il est nécessaire d'éviter cette caractéristique de la langue, qui est de lui accorder une quantité incroyable de flexibilité (ce qui est complètement différent de d'éviter les choses comme with). Cela dit, je vais regarder maintenant.

En tout cas, lorsque vous n'utilisez pas une sorte de cadre qui prend en charge automagic héritage (comme dojo.declare), ou lors de l'écriture d'un cadre d'objet indépendant, je prend actuellement l'approche suivante.

Définition:

var SomeObject = function() {
    /* Private access */
    var privateMember = "I am a private member";
    var privateMethod = bindScope(this, function() {
        console.log(privateMember, this.publicMember);
    });

    /* Public access */
    this.publicMember = "I am a public member";

    this.publicMethod = function() {
        console.log(privateMember, this.publicMember);
    };
    this.privateMethodWrapper = function() {
        privateMethod();
    }
};

Utilisation:

var o = new SomeObject();
o.privateMethodWrapper();

bindScope est une fonction d'utilité semblable à du Dojo dojo.hitch ou du Prototype Function.prototype.bind.

6voto

HappyCoder Points 477

Dans son livre, il s'appelle fonctionnel de l'héritage (page 52). Je ne l'utilise pas encore. Il est compréhensible si vous apprendre le javascript de Douglas. Je ne pense pas qu'il y est une meilleure approche. Celui-ci est bon parce qu'il:

  • permet à un programmeur de créer des membres privés

  • sécurise les membres privés et élimine cette opposition à faire semblant de vie privée (privée membres de démarrer avec _)

  • fait de l'héritage lisse et sans code inutile

Cependant, il a quelques inconvénients. Vous pouvez en lire plus à ce sujet ici: http://www.bolinfest.com/javascript/inheritance.php

1voto

MillsJROSS Points 741

Utilisez-vous ce genre de constructeur modèle?

J'ai utilisé cette formulation plus tôt, lorsque j'ai commencé l'apprentissage de JavaScript et suis tombé sur Douglas Crockford de la littérature.

Trouvez-vous qu'il compréhensible?

Tant que vous comprenez les fermetures, cette méthode est clair.

Avez-vous une meilleure?

Cela dépend de ce que vous essayez d'accomplir. Si vous essayez d'écrire une bibliothèque qui va être aussi idiot proof que possible, alors je peux tout à fait comprendre l'utilisation de variables privées. Il peut aider à empêcher les utilisateurs de par inadvertance perturber l'intégrité de votre objet. Oui, le coût en temps peut être légèrement plus grand (environ 3 fois plus), mais le coût du temps est un argument discutable jusqu'à ce qu'il est en fait affecter votre application. J'ai remarqué que le test mentionné dans un précédent post (test) ne tient pas compte de combien de temps il faut pour accéder à un objet de ses fonctions.

J'ai trouvé que le prototype ou le constructeur méthode conduit généralement à une plus rapide, le temps de la construction, oui, mais ça ne veut pas forcément gagner du temps dans la recherche. Il y a un coût supplémentaire de l'utilisation de la chaîne de prototype à trouver une fonction au lieu d'avoir une fonction directement attaché à l'objet que vous utilisez. Donc, si vous appelez un lot de prototypes de fonctions et non pas la construction d'un lot d'objets, il peut être plus judicieux d'utiliser Crockford du modèle.

J'ai tendance à ne pas aimer utiliser des variables privées, bien que, si je n'écris pas mon code pour un large public. Si je suis avec une équipe de gens qui sont tous capables de codeurs, je peux généralement, la confiance qu'ils vous savoir comment utiliser mon code si je code et commentaire bien moi-même. Puis-je utiliser quelque chose qui ressemble à Crockford du modèle sans membres privés/méthodes.

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