Adoptez la programation orinetée objet (POO) en javascript

Tout a commencé il y a quelques années quand j'ai du apprendre le Framework ExtJs. Ce framework ne ressemble en rien aux autres frameworks javascript comme JQuery, Prototype... En utilisant ExtJs, je me suis très vite aperçu qu'une programmation javascript type procédurale allait me poser beaucoup de problème pour la factorisation du code, sa maintenabilité et également la taille du code js qu'il faudra par la suite téléchrager dans le navigateur. ExtJs utilise le prototype de javascript pour créer des objets et le but de cet article est de vous initier a cette pratique.
Pour les curieux, un article sur la programmation orienté prototype: http://en.wikipedia.org/wiki/Prototype-based_programming

Pour faciliter les explications, je vais volontairement  faire le parrallèle avec la POO même si je ne devrais pas car les principes sont différents.
Il est possible de créer des (classes) objets qui doivent être instanciés et d'autres qui n'en on pas besoin un peu comme les classes static.

 

1. Un objet à instanciatier

a. Théorie

Loin de moi l'envie de faire de long discours théorique. Pour créer un objet il faut déclarer un fonction dans une variable et éventuellement déclarer les variables de la class dans cette fonction.

 
var maClass = function()
{
    this.var1 = null;
    this.var2 = true;
}

Les méthodes de la class sont à déclarer dans le prototype:

 
maClass.prototype = 
{
    method1: function()
    {
        if(this.var2 == true)
            alert('quelque chose');
 
        this.var2 = false;
    },
    method2: function(param)
    {
        this.var1 = param;
        this.method1();
    }
}

L'accès au membre de la class se fait avec le mot clé this.
L'utilisation de cette class se fait comme suit:

 
var objet = new maClass();
objet.method2('oups');

 

b. Exemple

Comme exemple, je vais utiliser un objet JS que j'ai crée pour controler un formulaire de mail. L'objet doit:
- controller que tous les champs sont remplis
- valider le format de l'adresse email
- valider la valeur d'un champs contre les robots
- soumettre le formulaire en ajax
- afficher les messages d'erreurs ou de succès

J'utilise JQuery pour la requete AJAX et la manipulation du DOM.

Initialisation de la class et des variables qui me permettront de savoir quelle erreur s'est produite durant la validation.

 
var sendMail = function()
{
        this.bChampsVide = false;
        this.bMailKo = false;
        this.bAntiRobot = false;
}
 

Dans le prototype je déclare 3 méthodes:
- submitForm: qui sera appelé lors de la soumission de mon formulaire.
- valideForm: qui sera appelé par la méthode précédente pour vérifier si le formulaire est correcte
- majMessage: pour afficher les messages

 
sendMail.prototype =
{
    submitForm: function(poForm) {
        if(this.valideForm(poForm)) {
            var that = this;
 
            $.ajax({
                url: poForm.action,
                cache: false,
                type: 'POST',
                data: $(poForm).serialize()+'&EnvoyerMail=EnvoyerMail',
                dataType: 'html',
                success: function(response) {
                    that.majMessage(response);
                },
                 error: function(){
                    that.majMessage('<p style="color:#F00;">Erreur inconnue.</p>');
                }
            });
        } else {
            var sMessage = '<ul style="color: #F00">';
            if(this.bChampsVide)
                sMessage += '<li>Tous les champs sont obligatoires.</li>';
            if(this.bMailKo)
                sMessage += '<li>Le format de l\'adresse mail n\'est pas valide.</li>';
            if(this.bAntiRobot)
                sMessage += '<li>Le controle anti spam est faux.</li>';
            sMessage += '</ul>';
 
            this.majMessage(sMessage);
        }
        return false;
    },
 
    valideForm: function(poForm){
        this.bChampsVide = false;
        this.bMailKo = false;
        this.bAntiRobot = false;
 
         var sRegexMail = /mail/ig,
             bReturn = true,
            aChamps = $(poForm).serializeArray();
 
        for(var i=0, l=aChamps.length; i < l; i++) {
            if(aChamps[i].name == 'controleAntiRobot'){
                if(aChamps[i].value != 29){
                    bReturn =  false;
                    this.bAntiRobot = true;
                }
            } else if(aChamps[i].name.match(sRegexMail)) {
                if(!aChamps[i].value.match(/^[_a-z0-9-]+(.[_a-z0-9-]+)*[^._-]@[a-z0-9-]+(.[a-z0-9]{2,4})*$/)) {
                    bReturn =  false;
                    this.bMailKo = true;
                } else if(aChamps[i].value == '') {
                    bReturn =  false;
                    this.bChampsVide = true;
                }
            } else if(aChamps[i].name == 'senderMessage') {
                continue;
            } else if(aChamps[i].value == ''){
                bReturn =  false;
                this.bChampsVide = true;
            }
        }
 
        return bReturn;
    },
 
    majMessage: function(sMessage) {
        $('#message').html(sMessage);
    }
}
 

L'utilisation de cet objet est très simple, il suffit de l'instancier dans la page du formulaire et d'appeler sa méthode submitForm() sur l'événement onsubmit du formulaire.

 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <script type="text/javascript" src="/sendMail.js"></script>
    <script type="text/javascript">
        var sendMailler = new sendMail();
    </script>
  </head>
  <body>
 
       <div id="message"></div>
       <form action="sendmail.php" onsubmit="return sendMailer.submitForm(this);"
       ........
       </form>
 
  </body>
</html>
 

 

2. Un objet sans instanciation

a. Théorie

Comme ci dessus, tout commence avec l'affectation d'une fonction à une variable, mais cette fois sans définir les variables de class à l'interieur.

 
var maClass = function(){};

Que ce soit les variables de class ou les méthodes, elles se définissent sans utiliser le prototype.

 
maClass.var1 = null;
maClass.var2 = true;
maClass.method1 = function()
    {
        if(this.var2 == true)
            alert('quelque chose');
 
        this.var2 = false;
    };
maClass.method2 = function(param)
    {
        this.var1 = param;
        this.method1();
    };

L'accès au membre de la class se fait toujours avec le mot clé this.
L'utilisation de cette class se fait sans utiliser le mot clé new:

 
maClass.method2('oups');

 

b. Exemple

On peut modifier le premier exemple pour utiliser ce style de notation et ne pas avoir à créer l'instance avant d'utiliser l'objet.

 
var sendMail  = function(){};
sendMail.bChampsVide = false;
sendMail.bMailKo = false;
sendMail.bAntiRobot = false;
 
sendMail.submitForm = function(poForm) {
        if(this.valideForm(poForm)) {
            var that = this;
 
            $.ajax({
                url: poForm.action,
                cache: false,
                type: 'POST',
                data: $(poForm).serialize()+'&EnvoyerMail=EnvoyerMail',
                dataType: 'html',
                success: function(response) {
                    that.majMessage(response);
                },
                 error: function(){
                    that.majMessage('<p style="color:#F00;">Erreur inconnue.</p>');
                }
            });
        } else {
            var sMessage = '<ul style="color: #F00">';
            if(this.bChampsVide)
                sMessage += '<li>Tous les champs sont obligatoires.</li>';
            if(this.bMailKo)
                sMessage += '<li>Le format de l\'adresse mail n\'est pas valide.</li>';
            if(this.bAntiRobot)
                sMessage += '<li>Le controle anti spam est faux.</li>';
            sMessage += '</ul>';
 
            this.majMessage(sMessage);
        }
        return false;
    };
 
sendMail.valideForm = function(poForm){
        this.bChampsVide = false;
        this.bMailKo = false;
        this.bAntiRobot = false;
 
         var sRegexMail = /mail/ig,
             bReturn = true,
            aChamps = $(poForm).serializeArray();
 
        for(var i=0, l=aChamps.length; i < l; i++) {
            if(aChamps[i].name == 'controleAntiRobot'){
                if(aChamps[i].value != 29){
                    bReturn =  false;
                    this.bAntiRobot = true;
                }
            } else if(aChamps[i].name.match(sRegexMail)) {
                if(!aChamps[i].value.match(/^[_a-z0-9-]+(.[_a-z0-9-]+)*[^._-]@[a-z0-9-]+(.[a-z0-9]{2,4})*$/)) {
                    bReturn =  false;
                    this.bMailKo = true;
                } else if(aChamps[i].value == '') {
                    bReturn =  false;
                    this.bChampsVide = true;
                }
            } else if(aChamps[i].name == 'senderMessage') {
                continue;
            } else if(aChamps[i].value == ''){
                bReturn =  false;
                this.bChampsVide = true;
            }
        }
 
        return bReturn;
    };
 
sendMail.majMessage = function(sMessage) {
        $('#message').html(sMessage);
    };
 

Et l''utilisation se fera comme suit:

 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <script type="text/javascript" src="/sendMail.js"></script>
  </head>
  <body>
 
       <div id="message"></div>
       <form action="sendmail.php" onsubmit="return sendMail.submitForm(this);"
       ........
       </form>
 
  </body>
</html>

 

 

Les exemples données ici sont très simplistes mais j'espère qu'ils vous auront données des idées et l'envie de changer votre façon de coder le javascript. De plus en plus le javascript devient une affaire de développeur et non plus de graphiste ou webmaster. Il est terminé le temps où l'on avait juste des alert() et quelques effets de couleurs sur une page. Les développements modernes nécessitent du code js de plus en plus complexe.

Il y a 1 commentaire

  • christian belibi03-18-2014 15:41:17

    cool ton article. Ne pourras-tu pas en faire un sur le développement MVC avec jquery, ce serait