W3docs

Getters e Setters em JavaScript

Aprenda getters e setters em JavaScript: sintaxe get/set, propriedades acessoras vs dados, validação, propriedades computadas e uso em classes.

A maioria das propriedades de objetos em JavaScript são propriedades de dados — elas simplesmente armazenam um valor. Mas os objetos também suportam propriedades acessoras: propriedades sustentadas por funções que são executadas sempre que a propriedade é lida ou escrita. Essas funções são chamadas de getters e setters. Para o mundo externo, uma propriedade acessora parece uma propriedade comum (user.age), mas por trás das cenas, o seu próprio código decide o que a leitura ou atribuição dela realmente faz.

Este guia cobre a sintaxe get/set, como as propriedades acessoras diferem das propriedades de dados, os casos de uso mais comuns (validação e valores computados), como getters e setters funcionam dentro de classes, e as armadilhas que vale a pena conhecer.

Introdução a Getters e Setters de Propriedades

Um getter é uma função que é executada quando você uma propriedade; seu valor de retorno torna-se o valor do acesso. Um setter é uma função que é executada quando você atribui a uma propriedade; ele recebe o valor atribuído como seu único argumento. Por serem funções, eles podem executar validação, calcular um resultado dinamicamente, registrar acessos ou atualizar outras propriedades — tudo enquanto o código que os chama usa a sintaxe comum de propriedade.

Sintaxe

Dentro de um literal de objeto, defina um getter com a palavra-chave get seguida de um método, e um setter com a palavra-chave set seguida de um método que recebe um parâmetro:

let obj = {
  get propName() {
    // getter, the code executed when obj.propName is read
  },
  set propName(value) {
    // setter, the code executed when obj.propName is written
  }
};

Você pode definir ambos, ou apenas um. Uma propriedade com apenas um getter é somente leitura; atribuir a ela não faz nada silenciosamente no modo não estrito e lança um TypeError no modo estrito. Uma propriedade com apenas um setter é somente escrita — lê-la retorna undefined.

Propriedades acessoras vs. propriedades de dados

Vale ser preciso sobre que tipo de propriedade um getter/setter cria. Uma propriedade comum como width: 5 é uma propriedade de dados com um value. Um par getter/setter, por sua vez, cria uma propriedade acessora que não tem value próprio — apenas funções get e set. Os dois são mutuamente exclusivos: um único descritor de propriedade não pode ter tanto um value quanto um get/set.

É por isso que os exemplos de validação abaixo mantêm o número real em um campo de apoio separado (_age): o acessor público age precisa de algum lugar para armazenar os dados, porque não tem um slot de valor próprio. Para inspecionar isso diretamente, veja Flags e descritores de propriedades.

Por que Usar Getters e Setters?

Getters e setters oferecem vários benefícios, incluindo:

  • Encapsulamento: Eles ocultam a representação interna por trás de uma interface pública estável. Você pode alterar posteriormente como um valor é armazenado sem quebrar o código que o lê.
  • Validação: Você pode rejeitar ou normalizar valores no setter antes de serem armazenados.
  • Propriedades Computadas: Um getter pode derivar seu resultado de outras propriedades, de modo que o valor esteja sempre atualizado e nunca fique desatualizado.
  • Compatibilidade retroativa: Se uma propriedade que costumava ser um campo simples precisar de lógica adicionada posteriormente, você pode substituí-la por um acessor com o mesmo nome — o código que a chama não muda.

Exemplos Práticos

Vamos mergulhar em alguns exemplos práticos para ilustrar como getters e setters podem ser usados em cenários do mundo real.

Exemplo 1: Objeto de Usuário com Validação de Idade

Considere um objeto de usuário onde queremos garantir que a propriedade age esteja sempre dentro de um intervalo razoável. O setter valida a entrada; o getter simplesmente retorna o campo de apoio.

javascript— editable

Exemplo 2: Criando Propriedades Computadas

Getters nos permitem criar propriedades que são calculadas dinamicamente com base em outros dados. Cada vez que area é lida, ela é recalculada, de modo que permanece sincronizada se width ou height mudar.

javascript— editable

Exemplo 3: Definindo acessores com Object.defineProperty

A sintaxe literal get/set é a maneira mais comum de declarar acessores, mas você também pode adicioná-los a um objeto existente — incluindo após sua criação — com Object.defineProperty. Isso é útil quando o nome da propriedade é dinâmico ou quando você quer controlar flags como enumerable.

javascript— editable

Boas Práticas

Ao usar getters e setters, considere as seguintes boas práticas para garantir que seu código seja limpo, sustentável e eficiente:

  • Evite Efeitos Colaterais em Getters: Getters devem ser rápidos e livres de efeitos colaterais, pois são frequentemente chamados implicitamente pelo motor ou durante a enumeração de propriedades.
  • Validação: Sempre valide os dados nos setters para evitar que dados inválidos ou prejudiciais sejam armazenados.
  • Convenções de Nomenclatura: Use um underscore inicial (_) para os nomes de propriedades de apoio para indicar que são privadas.
  • Serialização JSON: Note que JSON.stringify() ignora getters por padrão. Use uma função replacer ou serialização explícita se precisar incluir valores computados.

Casos de Uso Avançados

Nomes de Propriedades Dinâmicos

O JavaScript ES6 introduziu nomes de propriedades computados, que podem ser combinados com getters e setters para definir dinamicamente chaves acessoras com base em variáveis ou expressões.

javascript— editable

Integração com Classes

Getters e setters também são muito úteis na programação baseada em classes, oferecendo uma maneira de encapsular e controlar o acesso às propriedades de classe. A sintaxe é idêntica — basta escrever métodos get/set no corpo da classe — e eles são colocados no protótipo, de modo que cada instância os compartilha.

javascript— editable

Armadilhas Comuns

Alguns erros pegam os desenvolvedores de surpresa:

  • Recursão infinita por campo de apoio incorreto. Se um setter para name atribuir a this.name em vez de um campo separado como this._name, a atribuição aciona o setter novamente, indefinidamente. Sempre armazene o valor sob uma chave diferente.
  • Um getter sem setter é somente leitura. Atribuir a ele não faz nada (ou lança no modo estrito), o que pode parecer um bug silencioso.
  • JSON.stringify() chama getters mas ignora setters. Um getter computado é serializado (seu valor de retorno é incluído), mas não há como restaurá-lo por meio de um setter em JSON.parse() — você só recupera dados simples.
  • this segue o local da chamada. Dentro de um getter ou setter, this é o objeto em que a propriedade foi acessada. Se você copiar o acessor para outro objeto, this mudará de acordo — veja Métodos de objeto e "this".

O exemplo abaixo mostra a armadilha de recursão e sua correção:

javascript— editable

Conclusão

Dominar getters e setters de propriedades é um passo crucial para se tornar um desenvolvedor JavaScript proficiente. Esses recursos não apenas melhoram a funcionalidade e a segurança do seu código, mas também abrem caminho para bases de código mais legíveis e sustentáveis. Seguindo as boas práticas e os exemplos fornecidos neste guia, os desenvolvedores podem utilizar efetivamente getters e setters a seu favor, resultando em aplicações JavaScript mais robustas e eficientes.

Prática

Prática
Quais afirmações são verdadeiras sobre getters e setters em JavaScript?
Quais afirmações são verdadeiras sobre getters e setters em JavaScript?
Was this page helpful?