Une évolution possible des classes en JavaScript en 2019

Par:
fredericmazue

jeu, 24/01/2019 - 08:04

Le Technical Committee 39, ou TC39 travaille actuellement sur les nouvelles fonctionnalités à intégrer à ES2019. Les propositions sur lesquelles travaille ce comité sont disponibles sur GitHub.  Elles sont très nombreuses.

Parmi elles nous remarquons une évolution des déclarations de champs, dans une classe.

Soit une classe qui encapsule une compteur de clics sur un widget. Auparavant nous pouvions avoir : 

class Counter extends HTMLElement {
  clicked() {
    this.x++;
    window.requestAnimationFrame(this.render.bind(this));
  }
 
 constructor() {
    super();
    this.onclick = this.clicked.bind(this);
    this.x = 0;
  }
 
 connectedCallback() { this.render(); }
 
 render() {
    this.textContent = this.x.toString();
  }
}

window.customElements.define('num-counter', Counter);

Avec la nouvelle proposition, le code devient

class Counter extends HTMLElement {
  x = 0;

  clicked() {
    this.x++;
    window.requestAnimationFrame(this.render.bind(this));
  }
 
 constructor() {
    super();
    this.onclick = this.clicked.bind(this);
  }
 
 connectedCallback() { this.render(); }
 
 render() {
    this.textContent = this.x.toString();
  }
}
window.customElements.define('num-counter', Counter);

Le champ x peut aussi être déclaré sans initialisation. La proposition souligne qu'avec cette déclaration au début du code d'une classe, cette dernière est mieux auto-documentée, et que les instances passent par moins de changement d'état, puisque les champs ainsi déclarés sont toujours présents.

Avec cette proposition, les champs de classes peuvent être privés. Il n'est alors possible d'y accéder que via des accesseurs (getters et setters). Un champ privé est préfixé par le signe #, comme ceci :

class Counter extends HTMLElement {
  #x = 0;
 
 clicked() {
    this.#x++;
    window.requestAnimationFrame(this.render.bind(this));
  }
 
 constructor() {
    super();
    this.onclick = this.clicked.bind(this);
  }
 
 connectedCallback() { this.render(); }
 
 render() {
    this.textContent = this.#x.toString();
  }
}
window.customElements.define('num-counter', Counter);

Les méthodes de classes peuvent également être privées. Là encore elles seront préfixées par le signe #, comme ceci :

class Counter extends HTMLElement {
  #xValue = 0;
 
get #x() { return #xValue; }

  set #x(value) {
    this.#xValue = value;
    window.requestAnimationFrame(this.#render.bind(this));
  }

  #clicked() {
    this.#x++;
  }
 
constructor() {
    super();
    this.onclick = this.#clicked.bind(this);
  }
 
connectedCallback() { this.#render(); }
 
#render() {
    this.textContent = this.#x.toString();
  }
}
window.customElements.define('num-counter', Counter); 

Bien sûr, il ne s'agit pour l'instant que de propositions. L'avenir nous dira si celles-ci sont adoptées par le comité TC39.