Les meilleures pratiques Javascript OOP?

Je suis fatigué de voir des dizaines de façons différentes de faire une programmation orientée objet en Javascript. Quelqu'un peut-il me dire quelle technique je devrais utiliser compte tenu de vouloir travailler sur un projet à grande échelle et je veux que mon code soit une preuve future?

Ce ne sont que quelques lignes directrices rapides que j'ai proposées, si quelqu'un d'autre a quelque chose de significatif à ajouter, j'ai configuré cette réponse en tant que wiki communautaire, donc il devrait être assez facile pour que vous puissiez l'éditer.

  1. Espace de noms de vos objets pour vous assurer qu'ils ne seront jamais en conflit avec les bibliothèques JavaScript de tiers.
      Fenêtre ['Andrew'] ['JS'] = {
         AddEvent: function (el, evName) {/ * Stuff * /},
         Rectangle: fonction (largeur, hauteur) {/ * Stuff * /}
     }; 

    Alors, vous créez un objet rectangle en utilisant:

      Var myRect = new Andrew.JS.Rectangle (14,11); 

    Et alors, votre code n'interviendra jamais, ni ne sera entravé par le Rectangle d'autrui.

  2. Utilisez une stratégie de dénomination cohérente, en particulier:
    • Les noms d'objet devraient être mis en majuscule, tout le reste (variables, fonctions) devrait commencer par un caractère minuscule c.-à-d.
        Var myRect = new Andrew.JS.Rectangle (14,11);
       Document.write (myRect.getArea ()); 
    • Assurez-vous que tout est significatif, c'est-à-dire des verbes pour les méthodes, les noms et les adjectifs pour les paramètres.
  3. Assurez-vous que toutes les méthodes et tous les paramètres sont pertinents pour l'objet auquel ils appartiennent. Par exemple, dans cet exemple, la zone du rectangle peut être convertie en pieds carrés en utilisant la méthode inSquareFeet() .

      MyRect.getAreaObject (). InSquareFeet (); 

    Assurez-vous que inSquareFeet est une méthode de l'objet renvoyé par getAreaObject() et non une méthode de Andrew.JS.Rectangle

  4. Utilisez les constructeurs, ou plus précisément, essayez le plus dur possible de vous assurer qu'un objet n'a pas besoin d'une autre initialisation à utiliser une fois qu'il a été construit, donc au lieu de:
      Var Person = function ()
     {
         This.name = "";
         This.sayHello = function ()
         {
             Alerte (this.name + "dit 'Hello!'");
             Renvoie ceci;
         }
     }
    
     Var bob = new Person ();
     Bob.name = "Bob Poulton";
     Bob.sayHello (); 

    essayer:

      Var Personne = fonction (nom)
     {
         This.name = nom;
         This.sayHello = function ()
         {
             Alerte (this.name + "dit 'Hello!'");
             Renvoie ceci;
         }
     }
    
     Var bob = new Person ("Bob Poulton");
     Bob.sayHello (); 

J'utilise toujours John Resig:

http://ejohn.org/blog/simple-javascript-inheritance/

C'est simple et ne nécessite aucun cadre pour fonctionner.

Parce que vous travaillez sur un projet à grande échelle, je suggérerais un framework javascript comme mootools http://mootools.net/ .

Il a une bonne structure de classe et d'héritage.

Juste pour votre information, je pense que YUI offre quelques excellents tutoriels sur ce sujet

 //Create and define Global NameSpace Object ( function(GlobalObject, $, undefined) { GlobalObject.Method = function() { ///<summary></summary> } GlobalObject.Functionality = {}; }) (GlobalObject = GlobalObject || {}, jQuery); //New object for specific functionality ( function(Events, $, undefined) { //Member Variables var Variable; // (Used for) , (type) // Initialize Events.Init = function() { ///<summary></summary> } // public method Events.PublicMethod = function(oParam) { ///<summary></summary> ///<param type=""></param> } // protected method (typically define in global object, but can be made available from here) GlobalObject.Functionality.ProtectedMethod = function() { ///<summary></summary> } // internal method (typically define in global object, but can be made available from here) GlobalObject.InternalMethod = function() { ///<summary></summary> } // private method var privateMethod = function() { ///<summary></summary> } }) (GlobalObject.Funcitonality.Events = GlobalObject.Funcitonality.Events || {}, jQuery ) // Reusable "class" object var oMultiInstanceClass = function() { // Memeber Variables again var oMember = null; // // Public method this.Init = function(oParam) { oMember = oParam; for ( n = 1; i < oMemeber.length; i += 1 ) { new this.SubClass.Init(oMember[i]); // you get the point, yeah? } } this.Subclass = function() { this.Init = function() { } } } 

La force en est qu'il initialise automatiquement l'objet Global, vous permet de maintenir l'intégrité de votre code et organise chaque fonctionnalité dans un groupement spécifique par votre définition.

Cette structure est solide, présentant toutes les fonctions syntaxiques de base que vous attendez d'OOP sans les mots clés.

Il existe même des moyens ingénieux de configurer les interfaces. Si vous choisissez d'aller aussi loin, une recherche simple vous donnera de bons tutoriels et astuces.

La configuration même d'Intellisense est possible avec javascript et visual studio, puis définir chaque pièce et les références rend l'écriture javascript plus propre et plus gérable.

L'utilisation de ces trois méthodes selon votre situation permet de garder l'espace de noms global propre, de garder votre code organisé et de maintenir la séparation des préoccupations pour chaque objet .. s'il est utilisé correctement. Rappelez-vous, la conception orientée objet est inutile si vous n'utilisez pas la logique derrière l'utilisation d'objets!

Mon objet idéal pour OOP est comme utiliser une méthode Instance avec des prototypes:

Exemple:

 var Users = function() { var _instance; this.prototype.getUsername = function(){/*...*/} this.prototype.getFirstname = function(){/*...*/} this.prototype.getSecurityHash = function(){/*...*/} /*...*/ /*Static Methods as such*/ return { /*Return a small Object*/ GetInstance : function() { if(_instance == null) { _instnance = new Users(arguments); } return _instnance; //Return the object }, New: function() { _instnance = null; //unset It return this.GetInstnace(arguments); } } } 

Ensuite, j'utiliserais toujours comme:

 Firstname = Users.GetInstance('Robert','Pitt').getFirstname(); Username = Users.GetInstance().getUsername(); //Returns the above object. Me = Users.New('Robert',null); //Deletes the above object and creates a new instance. Father = Users.New('Peter','Piper'); //New Object Me.AddFather(Father); //Me Object. 

Et c'est le genre de route où je vais en train de construire une architecture JavaScript OO Style.

 function foo() { var bar = function() { console.log("i'm a private method"); return 1; }; var iAmAPrivateVariable = 1; return { publicMethod: function() { alert(iAmAPrivateVariable); }, publicVariable: bar() } } //usage var thing = foo() 

Il s'agit d'une approche fonctionnelle, et il y a beaucoup plus de choses (comme l'encapsulation), alors tout ce que vous allez voir

D'une manière générale, vous ne devriez pas faire OO en javascript, ce n'est pas une excellente langue pour de nombreuses raisons. Pensez à un schéma avec des crochets étonnants et des points-virgules, et vous commencerez à écrire la langue comme les pros. Cela étant dit, quelque temps OO est un meilleur ajustement. Dans ces cas, ce qui précède est généralement le meilleur pari

Pour amener les héritages dans le mélange

 function parent() { return { parentVariable: 2 }; } function foo() { var bar = function() { console.log("i'm a private method"); return 1; }; var iAmAPrivateVariable = 1; me = parent(); me.publicMethod = function() { alert(iAmAPrivateVariable); }; me.publicVariable = bar(); return me; } 

Cela rend les choses un peu plus compactées, mais accomplit le résultat final souhaité tout en adoptant une approche fonctionnelle des concepts OO (dans ce cas, en utilisant des fonctions de décorateur au lieu d'un héritage réel). Ce que j'aime de toute l'approche, c'est que nous traitons toujours les objets de la manière dont ils sont destinés à ce type de langue – un sac de propriété que vous pouvez attacher à la volonté.

Une autre note est que c'est très différent de ce que vous verrez la plupart du temps dans la plupart des emplois sur lesquels vous travaillez et souvent est très difficile à expliquer a) ce qui se passe, et b) pourquoi c'est une bonne idée Aux collègues.

J'utilise un tel modèle et je vous recommande de l'utiliser aussi:

 function Person(firstname, lastname, age) { var self = this; var _ = {}; // Private members. var firstname = firstname; var lastname = lastname; var age = age || 'unknown'; // Private methods. function first_letter_to_uppercase(str) { return str.charAt(0).toUpperCase() + str.substr(1); } // Public members and methods. _.get_age = function() { return age; } _.get_name = function() { return first_letter_to_uppercase(firstname) + ' ' + first_letter_to_uppercase(lastname); } return _; } var p = new Person('vasya', 'pupkin', 23); alert("It's " + p.get_name() + ', he is ' + p.get_age() + ' years old.') 

Vous pouvez essayer avec un objet simple, utile et rapide:

 var foo = { foo1: null, foo2: true, foo3: 24, foo4: new Array(), nameOfFunction1: function(){ alert("foo1"); }, nameOfFunction2: function(){ alert("foo2"); }, } 

Pour l'utiliser, vous devez créer une instance de cet objet et utiliser comme objet dans java:

 foo.nameOfFunction2(); 

Vous pouvez également vérifier ce lien vers une autre solution: http://www.javascriptkit.com/javatutors/oopjs.shtml

J'espère que cela répond à votre question.