DEV Community

Cover image for POO et encapsulation JS
DUVAL Olivier
DUVAL Olivier

Posted on • Updated on

POO et encapsulation JS

Sommaire

TL;DR;

Après plus de 5 années à développer en TypeScript (pour Angular), j'avais envie de taper un peu de JavaScript vanilla, sur des concepts et fondamentaux de ce langage.

Sur les projets des dernières années, en MVC / Webforms, MVT ou AngularJs, j'ai pu m'apercevoir de pratiques que j'estime mauvaises chez certains devs pour le développement en JavaScript : une approche uniquement par l'empilement de fonctions et non objet, ce qui amène un moment donné à du spaghetti code et cela devient illisible et (très) difficile à maintenir.

L'encapsulation en programmation objet permet, sur un objet, d'exposer au client de cet objet uniquement des méthodes / fonctions dites publiques et de cacher / masquer (rendre privé) toutes les fonctions utiles à l'objet et à son comportement, autrement dit, l'implémentation réelle sera interne à l'objet : l'accès et l'état des propriétés de cet objet ne seront accessibles que par le biais de ces fonctions publiques, cela protège et simplifie le comportement de cet objet.

Il faudra instancier l'objet pour l'utiliser.

Dans les exemples ci-après, nous allons utiliser ce principe POO en Javascript avec différentes implémentations ou façons de faire et un exemple plus élaboré avec un chrono et un compte à rebours.

Pour me simplifier la tâche, et comme disent mes enfants, "flemme", j'ai utilisé Boostrap pour rendre joli le tout, et jQuery pour l'utilisation des éléments du DOM (sélecteurs), bien que j'aurais pu utiliser le querySelector.

Différentes implémentations

Imaginons un objet avec une propriété et des méthodes pour y accéder en lecture ou en écriture et pour concaténer avec une chaîne, il y a plusieurs implémentations possible en utilisant le scope et/ou closures des fonctions, en ES5. Ma préférence va pour la 3ème forme.

1ère forme

  • déclaration
;
var MonObjet = MonObjet || {};
(function() {
   /*== private ==*/
   var _property = '';
   var _concat = function(val) {
     _property = `${_property}${val}`;
     return _property;
   }

   /*== public ==*/
   MonObjet.get = function() {
     return _property;
   }
   MonObjet.set = function(val) {
     _property = val;

   }
   MonObjet.concatWith = function(val) {
     return _concat(val);
   }
})();
Enter fullscreen mode Exit fullscreen mode
  • appel
(function() {
    console.log(MonObjet.get());
    MonObjet.set('Olivier');
    var concat = MonObjet.concatWith(' Duval');
    console.log(concat); // affiche Olivier Duval
})();
Enter fullscreen mode Exit fullscreen mode

2ème forme

  • déclaration
function MonObjet2() {
    /*== private ==*/
    var _property = '';
    var _concat = function(val) {
        _property = `${_property}${val}`;
        return _property;
    };

    /*== public ==*/
    this.get = function() {
        return _property;
    }
    this.set = function(val) {
        _property = val;
    }
    this.concatWith = function(val) {
        return _concat(val);
    }
}
Enter fullscreen mode Exit fullscreen mode
  • appel
(function() {
    var monObjet2 = new MonObjet2();
    console.log(monObjet2.get());
    monObjet2.set('Valérie')
    var concat2 = monObjet2.concatWith(' Aubin');
    console.log(concat2); // affiche Valérie Aubin
})();
Enter fullscreen mode Exit fullscreen mode

3ème forme

  • déclaration
var MonObjet3 = function() {
    /*== private ==*/
    var _property = '';
    var _concat = function(val) {
        _property = `${_property}${val}`;
        return _property;
    };
    var _get = function() {
        return _property;
    };
    var _set = function(val) {
        _property = val;
    };

    /*== public ==*/
    return ({
        get: _get,
        set: _set,
        concatWith: _concat
    });
};
Enter fullscreen mode Exit fullscreen mode
  • appel
(function() {
    var monObjet3 = MonObjet3();
    console.log(monObjet3.get());
    monObjet3.set('John');
    var concat3 = monObjet3.concatWith(' Do');
    console.log(concat3); // affiche John Do
})();
Enter fullscreen mode Exit fullscreen mode

Chrono et compte à rebours

Un usage plus poussé consisterait à créer des objets pour gérer

  • un formulaire chrono / compte à rebours : saisie d'un nombre puis activation d'un chrono ou d'un compte à rebours
  • un formulaire couleur : l'appui sur le bouton après sélection d'une couleur modifie la couleur du bouton
  • une classe compteur pour gérer la logique du chrono ou du compte à rebours

Je vous laisse regarder les démos et leur code !

Image description

Image description

Sources et démos

Démo exemples d'implémentations ouvrir la console !

Démo chrono / compte à rebours et couleur.

Sources sur Github.

Latest comments (0)