Les attributs privés en JavaScript

Aussi étonnant que cela puisse paraître, nous ne pouvons pas avoir d'attributs ou de méthodes privés dans une classe en JavaScript. La solution aujourd'hui est de le simuler grâce au design pattern module et aux closures.

Toutefois, le standard est en train d'évoluer et il est probable que le langage intègre prochainement le support d'une telle notion. Nous allons voir ça dans cet article.

Draft Stage 3

Nous avons évoqué cette feature dans l'article "Roadmap ES.Next, où en sommes-nous ?". Une draft qui atteint le stage 3 est une draft en cours de finalisation.

La proposition est disponible sur GitHub : Private methods and getter/setters for JavaScript classes

Malheureusement, il n'y a pas eu d'évolution depuis 6 mois, elle n’intégrera pas la nouvelle mouture du standard qui sortira cette année : ES2020.

Concrètement, qu'est-ce que cela apporte ?

Quand on parle d'attributs et de méthodes privés dans une classe, il est question de POO.

En voici un exemple :

class Younup {
  #you = 0;

  constructor() {}

  up() {
    this.#you++;
  }

  #upup() {
    this.#you = this.#you + 2;
  }

  getYou() {
    return this.#you;
  }

  addYouYouAndGetYou() {
    this.#upup();
    return this.#you;
  }
}

Dans ce cas précis, le symbole # permet :

  • soit de rendre votre attribut privé,
  • Soit de rendre votre méthode privée.

Il nous est donc impossible d'appeler ou d'accéder à un attribut privé en dehors de classe. Ce code, par exemple, n'est pas valide :

const younup = new Younup();
younup.up();
console.log(younup.#you);    // SyntaxError
younup.#upup();              // SyntaxError

Et dans le monde réel ?

Sans être encore dans le standard, il peut arriver que certains navigateurs embarquent des fonctionnalités expérimentales dans leur dernière version.

Je vous invite à consulter deux excellents sites pour cela : https://caniuse.com/ et https://developer.mozilla.org/fr/.

Au moment de rédiger cet article, seuls les attributs privés ont été implémenté dans trois navigateurs : Chrome 74, Edge 79 et Opera 62.

Les méthodes ne sont pas encore concernées à ce jour.

Bonjour TypeScript 3.8 !

TypeScript a décidé de prendre également les devants et d'intégrer les attributs privés.

Voici un exemple de classe avec les deux façons différentes de déclarer des attributs privés en TypeScript :

class Younup {
  #you = 0;
  private you = 0;

  constructor() {}

  getPrivateYou() {
    return this.you;
  }

  getRealPrivateYou() {
    return this.#you;
  }
}

Alors, à quel moment peut-on utiliser le mot clé private ou le # ?

La feature étant relativement récente, il n'y a pas réellement de discussion à ce sujet.

Avantages du # :

  • Véritable privé, nous ne pouvons pas accéder au private d'un objet, comme nous pourrions le faire avec un (obj as any).variablePrivee ;
  • Adoption du futur standard.

Inconvénients du # :

  • # n'est pas assez répandu sur les navigateurs. "Under the hood", TypeScript utilise une WeakMap pour garder la référence de la classe et des variables privées. Plus l'utilisation de la classe sera grande, plus la consommation en mémoire le sera également.
  • Même s'il n'a aucune valeur au runtime, le private est beaucoup plus efficace (il n'est pas transpilé).

Conclusion

Un cap supplémentaire est en train d'être franchi, même si l'adoption complète est trop limitée pour s'y aventurer sur des projets importants.

L'adoption du # est donc soumis à la cible de vos plateformes et de vos utilisations.

Benjamin

Benjamin, expert front Younup, aime le code smart, compréhensible et réutilisable. Malgré ses différentes tentatives de supprimer ES4 et Angular3 il a échoué, damn !

Ses technos de prédilection sont le Typescript, il adore transpiler en ES3 pour Internet Explorer, mais aussi le JavaScript. Hé oui, on peut tout faire avec (enfin aussi n’importe quoi…). Avouons-le, il a aussi un petit crush pour les PWA. Quand le web vient titiller le monde des apps natives et apporter une concurrence ultra positive !

Et si vous ne trouvez pas Benjamin derrière son écran se tirant les cheveux pour avoir oublié un CTRL+S, il devrait être sur un terrain, non loin du Saint Laurent, à travailler ses shoots…

Retours aux publications