POO et encapsulation JS
Tags: javascript, poo, encapsulation
Published: 2022-06-29 13:55:14


## Sommaire
  * [TL;DR;](#intro)
  * [Exemples d'implémentations](#samples)
  * [Chrono et couleur](#chrono)
  * [Sources et démos](#conclusion)

# TL;DR; <a name="intro"></a>

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](https://getbootstrap.com/) pour rendre joli le tout, et [jQuery](https://jquery.com/) pour l'utilisation des éléments du DOM (sélecteurs), bien que j'aurais pu utiliser le [querySelector](https://developer.mozilla.org/fr/docs/Web/API/Document/querySelector).

# Différentes implémentations <a name="samples"></a>

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](https://fr.wikipedia.org/wiki/ECMAScript). Ma préférence va pour la 3ème forme.

**1ère forme**

- déclaration

```javascript
;
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);
   }
})();
```

- appel

```javascript
(function() {
    console.log(MonObjet.get());
    MonObjet.set('Olivier');
    var concat = MonObjet.concatWith(' Duval');
    console.log(concat); // affiche Olivier Duval
})();
```

**2ème forme**

- déclaration

```javascript
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);
    }
}
```
- appel

```javascript
(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
})();
```

**3ème forme**

- déclaration

```javascript
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
    });
};
```

- appel

```javascript
(function() {
    var monObjet3 = MonObjet3();
    console.log(monObjet3.get());
    monObjet3.set('John');
    var concat3 = monObjet3.concatWith(' Do');
    console.log(concat3); // affiche John Do
})();
```

# Chrono et compte à rebours <a name="chrono"></a>

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/foph9dsn4jpgj1evud8w.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1g9ftyihlft2ao72k778.png)

# Sources et démos <a name="conclusion"></a> 

[Démo exemples d'implémentations](https://zorky.github.io/encapsulation_js/samples.html) ouvrir la console !

[Démo chrono / compte à rebours et couleur](https://zorky.github.io/encapsulation_js/).

Sources sur [Github](https://github.com/zorky/encapsulation_js).