Métodos estáticos em JavaScript pertencem à classe, não à instância
A maioria dos métodos que você escreve em uma classe opera sobre uma instância específica — um determinado user, um determinado circle. Com os métodos estáticos é diferente: eles pertencem à própria classe. Você os chama pelo nome da classe, e não a partir de uma instância.
double pertence a MathUtils, não às instâncias dela. Criar uma instância não ajuda em nada — m.double é undefined. Isso é o oposto dos métodos comuns, que vivem nas instâncias (tecnicamente, no prototype) e são invisíveis para a classe em si.
O modelo mental é o seguinte: a palavra-chave class cria duas coisas — um conjunto de métodos de instância (usados por new MathUtils()) e um conjunto de métodos estáticos (usados diretamente em MathUtils). A palavra-chave static é o que define em qual desses dois "baldes" cada membro vai parar.
O uso clássico: factory methods
O motivo mais comum para escrever um método estático é criar um construtor alternativo. O constructor de verdade recebe os argumentos que recebe, mas muitas vezes você quer outras formas de montar o objeto — a partir de um JSON, de uma linha do banco de dados ou de uma URL.
fromJSON não usa um usuário — ele produz um. É justamente nesse tipo de situação que um método estático se encaixa bem. A alternativa seria criar uma função solta parseUser, mas manter isso dentro da classe agrupa comportamentos relacionados e deixa a intenção clara no ponto de chamada.
Propriedades estáticas
Você também pode anexar dados diretamente à classe:
Circle.PI é compartilhado entre todos os círculos — é uma constante da classe, não uma cópia em cada instância. Dentro de métodos de instância, você acessa essa constante pelo nome da classe (Circle.PI), nunca via this.
Propriedades estáticas caem bem em configurações, caches compartilhados entre instâncias, contadores e constantes no nível da classe.
O this dentro de um método estático é a própria classe
Num método comum, this aponta para a instância. Já num método estático, this aponta para a classe:
this.count dentro de increment é o mesmo que Counter.count. Pode parecer estranho no começo, mas é justamente isso que faz a herança de métodos estáticos funcionar — this se refere à classe pela qual você chamou o método, não à classe que o definiu.
Herança de métodos estáticos em JavaScript
Métodos estáticos são herdados pelas subclasses. E como this aponta para a classe em que o método foi chamado, os factory methods já devolvem automaticamente a subclasse correta:
Animal.create usa new this(name). Quando você chama Dog.create("Rex"), o this é Dog, então new this(name) constrói um Dog. Se escrevêssemos new Animal(name) ali, o resultado seria sempre um Animal, quebrando o padrão. Esse é o principal motivo de o this dentro de métodos estáticos apontar para a própria classe.
Método estático vs. método de instância: comparação prática
Olha a mesma lógica implementada nos dois estilos:
Os dois fazem a mesma conta. A versão de instância lê os dados de this.celsius. Já a versão estática recebe a entrada como argumento. Use o método de instância quando a operação for "algo que este objeto faz"; use o método estático quando for "algo que esta classe sabe calcular a partir de entradas".
Static blocks para inicialização
Às vezes, inicializar uma propriedade estática exige mais do que uma única expressão — pode envolver um loop, um condicional ou vários valores que dependem uns dos outros. É aí que entram os static blocks:
Um bloco static { ... } roda uma única vez, no momento em que a classe é definida. Dentro dele, this é a própria classe. Use para configurações que envolvam vários passos; quando for só uma atribuição, um campo estático comum deixa tudo mais legível.
Membros estáticos privados
Campos estáticos também podem ser privados — basta usar o prefixo #. Eles só ficam acessíveis de dentro da própria classe:
#nextId fica trancado dentro da classe. Código externo até pode chamar IdGenerator.next(), mas não consegue ler nem resetar o contador. Os campos privados vão ganhar uma página só pra eles daqui a pouco, mas já vale saber que a combinação static + # funciona numa boa.
Quando não usar static
Métodos estáticos são ótimos para agrupar funções auxiliares, mas isso não é desculpa para transformar toda utilidade em classe. Se você tem um arquivo cheio de funções independentes, exporte as funções — não enrole tudo numa classe só com métodos estáticos para servir de namespace. Um módulo já faz esse papel, e faz de forma bem mais limpa.
Apele para static quando:
- A função realmente pertence à classe (factory, conversor, validador daquele tipo).
- Você precisa de um estado compartilhado entre todas as instâncias da classe.
- Uma subclasse pode querer sobrescrever ou herdar esse comportamento.
Fora esses casos, uma função solta é a ferramenta mais simples.
A seguir: campos privados
Você viu o #nextId passar rapidinho — essa é a sintaxe de campo privado do JavaScript. Funciona tanto para membros de instância quanto estáticos, e é a forma moderna de esconder detalhes de implementação dentro de uma classe. É esse o próximo assunto.
Perguntas frequentes
O que é um método estático em JavaScript?
Um método estático pertence à própria classe, e não às instâncias dela. Você o declara com a palavra-chave static e chama diretamente na classe: MinhaClasse.fazerAlgo(). As instâncias não conseguem acessá-lo via this.fazerAlgo() — só a classe tem esse acesso.
Quando usar um método estático em vez de um método de instância?
Use um método estático quando a função tem relação com a classe mas não precisa ler nem alterar uma instância específica. Casos clássicos: factory methods como User.fromJSON(...), utilitários como Math.max e constantes que fazem sentido agrupar na classe como um namespace. Se o método depende do this apontar para uma instância, aí sim ele precisa ser de instância.
Métodos estáticos conseguem acessar propriedades de instância?
Diretamente, não. Dentro de um método estático, o this se refere à classe, não a uma instância — então this.name lê uma propriedade estática, e não um campo da instância. Se você precisa dos dados da instância, passe ela como argumento: static summarize(user) { return user.name; }.
Métodos estáticos são herdados em JavaScript?
Sim. Quando uma subclasse faz extends de uma classe pai, os métodos estáticos do pai ficam disponíveis na subclasse também. Dentro de um método estático, o this aponta para a classe em que ele foi chamado, e é justamente isso que faz os factory methods estáticos funcionarem corretamente em subclasses.