Certaines fonctions appartiennent clairement à un modèle sans appartenir à un objet précis : convertir une unité, valider une entrée avant construction, compter les instances créées. Les ranger dans une méthode ordinaire obligerait à fabriquer un objet pour rien.
static résout ce décalage en attachant le membre à la classe elle-même.
Définition
static précède une méthode, un champ ou un accesseur dans le corps d'une class. Le membre obtenu s'appelle sur la classe, jamais sur une instance, et ne participe pas à l'état des objets créés.
class Temperature {
static ZERO_ABSOLU = -273.15;
constructor(celsius) {
this.celsius = celsius;
}
static depuisFahrenheit(degres) {
return new Temperature((degres - 32) / 1.8);
}
}
console.log(Temperature.ZERO_ABSOLU); // -273.15
console.log(Temperature.depuisFahrenheit(212).celsius); // 100
const releve = new Temperature(20);
console.log(releve.depuisFahrenheit); // undefinedLa dernière ligne surprend souvent : le membre statique n'existe pas sur les instances. Il n'est pas caché, il n'est simplement pas là, et une tentative d'appel lève une erreur de type.
Statique ou d'instance, comment choisir
| Critère | Membre statique | Membre d'instance |
|---|---|---|
| Appelé sur | La classe | Un objet créé avec new |
| Valeur de this | La classe elle-même | L'objet courant |
| Accès aux données de l'objet | Aucun | Complet |
| Usage typique | Constante, fabrique, utilitaire | Comportement d'un objet |
La règle de décision tient en une question : la fonction a-t-elle besoin des données d'un objet particulier. Si la réponse est non, le membre statique dit exactement cela au lecteur, et évite un objet créé sans raison.
Un état partagé par toute la classe
L'autre usage courant est la donnée qui appartient au modèle et non aux objets : un compteur, un cache, une limite. Un champ d'instance ne conviendrait pas, puisque chaque objet en garderait sa propre copie.
class Ticket {
static #compteur = 0;
constructor() {
Ticket.#compteur += 1;
this.numero = Ticket.#compteur;
}
static combien() { return Ticket.#compteur; }
}
new Ticket();
new Ticket();
console.log(Ticket.combien()); // 2Le champ statique privé sert ici de compteur partagé par toutes les instances, inaccessible depuis l'extérieur. Chaque objet lit et incrémente une valeur unique, ce qu'aucun champ d'instance ne saurait faire.
Un membre statique est hérité : une classe qui utilise extends peut appeler les méthodes statiques de son parent sur elle-même. C'est ce qui permet à une fabrique déclarée en haut de la hiérarchie de servir à toute la descendance.
Questions fréquentes
Quelle différence avec une simple fonction exportée ?
Techniquement peu de chose : les deux font le même travail. La méthode statique gagne quand la fonction n'a de sens qu'avec la classe, parce qu'elle reste à côté du modèle et se lit avec lui. Une fonction indépendante gagne quand elle sert ailleurs, et se laisse alors publier avec export sans traîner une classe entière derrière elle.
Que vaut this dans une méthode statique ?
Il désigne la classe sur laquelle l'appel a été fait, pas une instance. Cette précision compte avec l'héritage : si une classe fille appelle une fabrique déclarée dans le parent, this désigne la fille, et une construction écrite avec ce mot-clé produit donc bien une instance de la fille.
Peut-on déclarer une constante statique ?
Un champ statique en tient lieu, comme le zéro absolu de l'exemple, mais rien n'empêche de le réécrire depuis l'extérieur. Pour une vraie protection, déclarez le champ privé avec un dièse et exposez-le par un accesseur statique en lecture seule. Le mot-clé const, lui, ne s'emploie pas dans le corps d'une classe.