Sobes.tech
Middle+

O que sabes sobre os descritores?

sobes.tech IA

Resposta da IA

Os descritores em JavaScript são objetos que descrevem várias propriedades de uma propriedade de um objeto, como o seu valor (value), a possibilidade de escrita (writable), a possibilidade de enumeração (enumerable) e a possibilidade de configuração (configurable). Existem também descritores com getters e setters.

Existem dois tipos de descritores:

  • Descritores de dados: Contêm o valor da propriedade.

    • value: O valor da propriedade. Pode ser de qualquer tipo de dado válido.
    • writable: Um valor booleano. Se for true, o valor da propriedade pode ser alterado (obj.prop = newValue). Por padrão, é false para propriedades de acesso e true para propriedades de dados criadas por atribuição normal.
    • enumerable: Um valor booleano. Se for true, a propriedade será visível durante a iteração sobre as propriedades do objeto (por exemplo, em um ciclo for...in ou usando Object.keys()). Por padrão, é false para propriedades adicionadas com Object.defineProperty e true para propriedades criadas por atribuição normal.
    • configurable: Um valor booleano. Se for true, as características do descritor (exceto value e writable quando mudam de dados para acessórios) podem ser modificadas, e a propriedade pode ser eliminada. Por padrão, é false para propriedades adicionadas com Object.defineProperty (exceto value) e true para propriedades criadas por atribuição normal. Uma vez configurado como não configurável, não pode ser alterado novamente. Pode diminuir a writable de true para false, mas não o contrário num getter/setter não configurável.
  • Descritores de acessórios: Definem funções que serão chamadas ao obter (getter) ou definir (setter) o valor da propriedade.

    • get: Função chamada ao ler a propriedade. O resultado desta função torna-se o valor da propriedade. Não aceita argumentos.
    • set: Função chamada ao escrever na propriedade. Aceita um argumento, que é o novo valor a definir.
    • enumerable: Um valor booleano (semelhante aos descritores de dados).
    • configurable: Um valor booleano (semelhante aos descritores de dados).

Não se devem misturar descritores: uma propriedade tem ou value e writable, ou get e set.

Descritores são usados para gerir as propriedades de um objeto a um nível mais baixo do que a atribuição normal, em particular através dos métodos Object.defineProperty(), Object.defineProperties(), Object.getOwnPropertyDescriptor(), Object.getOwnPropertyDescriptors(), Object.create().

Exemplo de criação de uma propriedade com um descritor de dados:

// Criar um objeto vazio
const obj = {};

// Definir a propriedade 'name' com um descritor de dados
Object.defineProperty(obj, 'name', {
  value: 'Alice',
  writable: false, // A propriedade não pode ser alterada
  enumerable: true, // A propriedade será enumerável
  configurable: false // As características da propriedade não podem ser alteradas, a propriedade não pode ser eliminada
});

console.log(obj.name); // Vai mostrar: Alice

// Tentar alterar a propriedade (será ignorado em modo estrito ou lançará erro)
obj.name = 'Bob';
console.log(obj.name); // Vai mostrar: Alice

// Tentar eliminar a propriedade (será ignorado ou lançará erro)
delete obj.name;
console.log(obj.name); // Vai mostrar: Alice

Exemplo de criação de uma propriedade com um descritor de acessórios:

// Criar um objeto com uma variável privada
const user = {
  _firstName: 'John', // Variável privada por convenção
  _lastName: 'Doe'
};

// Definir a propriedade 'fullName' com um descritor de acessórios
Object.defineProperty(user, 'fullName', {
  get() {
    // Getter: devolve o nome completo
    return `${this._firstName} ${this._lastName}`;
  },
  set(value) {
    // Setter: divide o nome completo em partes e atualiza as variáveis privadas
    const parts = value.split(' ');
    this._firstName = parts[0];
    this._lastName = parts[1];
  },
  enumerable: true, // A propriedade será enumerável
  configurable: true // As características da propriedade podem ser alteradas, a propriedade pode ser eliminada
});

console.log(user.fullName); // Vai mostrar: John Doe

user.fullName = 'Peter Pan';
console.log(user._firstName); // Vai mostrar: Peter
console.log(user._lastName); // Vai mostrar: Pan
console.log(user.fullName); // Vai mostrar: Peter Pan

O uso de descritores permite criar propriedades imutáveis, propriedades com cálculo preguiçoso, propriedades com controlo de acesso (getters/setters) e gerir de forma mais flexível o comportamento dos objetos.