O que são getters e setters nas classes ECMAScript 6?

102

Estou confuso quanto ao ponto de getters e setters nas classes ECMAScript 6. Qual é o propósito? Abaixo está um exemplo a que me refiro:

class Employee {

    constructor(name) {
        this._name = name;
    }

    doWork() {
        return `${this._name} is working`;
    }

    get name() {
        return this._name.toUpperCase();
    }

    set name(newName){
        if(newName){ 
            this._name = newName;
        }
    }
}
TruMan1
fonte
1
É semelhante aos do C #, se você souber sobre isso.
Arturo Torres Sánchez
Um bom artigo explicando exatamente isso pode ser encontrado em: coryrylan.com/blog/javascript-es6-class-syntax "Em nossa classe acima, temos um getter e um setter para nossa propriedade de nome. Usamos a convenção '_' para criar um campo de apoio para armazenar nossa propriedade de nome. Sem isso, toda vez que get ou set for chamado, causaria um estouro de pilha "... Também fala que a variável não é realmente 'privada', mas existem inúmeras novas maneiras de criar vars privados em Classes JS; meu favorito é apenas usar o
texto digitado

Respostas:

108

Esses setter e getter permitem que você use as propriedades diretamente (sem usar o parêntese)

var emp = new Employee("TruMan1");

if (emp.name) { 
  // uses the get method in the background
}

emp.name = "New name"; // uses the setter in the background

Isso serve apenas para definir e obter o valor da propriedade.

David Laberge
fonte
1
Você quis dizer propriedade em vez de atributo? Um pouco confuso para mim
Krizzu,
Bom olho, @Krizzu. Os atributos existem em JavaScript e são coisas completamente diferentes das propriedades. A resposta realmente se refere a propriedades e não a atributos. Eu editei a resposta. Não acho que o respondente se importará. :)
Ray Toal
Não tenho certeza se isso é realmente uma vantagem, de alguma forma esconde a noção de usar setters / getters. Um cliente de uma classe pode pensar que usa propriedades diretamente, onde não é apropriado, mas eu concordo que adere ao princípio de ocultação de informações / detalhes. Talvez se usarmos isso, consequentemente, torna o uso mais fácil e eu só tenho que me acostumar mais com isso ...
Christof Kälin
Você pode passar vários parâmetros em um setter, se sim, como usá-lo? @David Laberge
Vignesh S
Se você deseja criar setters e getters manualmente, aqui está um bom exemplo de coryrylan.com/blog/javascript-es6-class-syntax Set: set name(newName) { this._name = newName; }Get:get name() { return this._name.toUpperCase(); }
Jim Doyle
48

Getters e setters no ES6 têm a mesma finalidade que em outros idiomas ... incluindo ES5. ES5 já permite getters e setters via Object.defineProperty, embora sejam menos limpos e mais complicados de usar.

Efetivamente, getters e setters permitem que você use notação de acesso de propriedade padrão para leituras e gravações, enquanto ainda tem a capacidade de personalizar como a propriedade é recuperada e transformada sem a necessidade de métodos getter e setter explícitos.

Na classe Employee acima, isso significaria que você poderia acessar a namepropriedade assim:

console.log(someEmployee.name);

Seria olhar como um acesso a propriedade normal, mas seria realmente chamar toUpperCaseo nome antes de devolvê-lo. Da mesma forma, fazendo isso:

someEmployee.name = null;

acessaria o setter e não modificaria a _namepropriedade interna por causa da cláusula de guarda introduzida no namesetter.

Consulte também a pergunta geral Por que usar getters e setters? para obter mais informações sobre por que é útil modificar a funcionalidade de acesso de membro.

Alexis King
fonte
3

Os getters e setters ES6 têm uma motivação substancialmente diferente de conceitos semelhantes em Java.

Em Java, getters e setters permitem que uma classe defina um JavaBean. O objetivo dos getters e setters é que eles permitem que o bean tenha uma "interface" completamente ortogonal daquela implícita nos campos públicos. Portanto, posso ter um campo "nome" que NÃO é uma propriedade JavaBean e posso ter um "endereço" de propriedade JavaBean que NÃO é um campo.

As propriedades JavaBean também são "detectáveis" por milhares de estruturas (Hibernate, por exemplo) por meio de reflexão Java. Portanto, getters e setters fazem parte de um método padrão para "expor" as propriedades do bean.

Getters e setters, sendo funções, também têm o valor de "abstrair" a implementação. Pode ser um campo ou um valor calculado ("sintético"). Portanto, se eu tiver uma propriedade de bean chamada "zipcode", ela começa como string armazenada. Agora, suponha que eu queira alterá-lo para um valor calculado de endereço / cidade / estado.

Se eu usar um campo, este código será quebrado:

      String zipcode = address.zipcode();

Mas se eu usar um getter, isso não quebra:

      String zipcode = address.getZipcode();

JavaScript não tem nada como JavaBeans. Até onde eu li, o valor pretendido de GET e SET é limitado às propriedades "sintéticas" (calculadas) mencionadas anteriormente.

Mas é um pouco melhor do que o java porque, embora o Java não permita que você converta de forma compatível um "campo" em um método, o ES6 GET e SET permitem isso.

Ou seja, se eu tiver:

       var zipcode = address.zipcode;

Se eu alterar o CEP de uma propriedade de objeto padrão para um getter, o código acima agora chama a função GET.

Observe que, se eu não incluísse GET na definição, isso NÃO invocaria o método GET do código postal. Em vez disso, ele simplesmente atribuiria o código postal da função ao var.

Portanto, acho que essas são algumas distinções importantes para entender entre getters e setters Java e JavaScript ES6.

DaBlick
fonte
0
class Employee {

    constructor(name) {
      this._name = name;
    }

    doWork() {
      return `${this._name} is working`;
    }

    get name() {
      // when you get this by employeeInstance.mame
      // the code below will be triggered
      // and you can do some logic here
      // just like `console.log` something you want
      console.log('get triggered!')
      return this._name.toUpperCase();
    }

    set name(newName) {
      // the same as `get`
      // when you employeeInstance.mame = 'xxx'
      // the code blew will be trigged
      // and you can also do some logic 
      // like here is a `console.log` and `if check`
      console.log('set triggered!')
      if (newName) {
        this._name = newName;
      }
    }
  }

  const employeeInstance = new Employee('mike')
  employeeInstance.name
  employeeInstance.name = '' // this won't be success, because the `if check`
  console.log(employeeInstance.name)

  // => 
  // get triggered
  // set triggered
  // get triggered
  // MIKE

De qualquer forma, o gettere setteré como um espião. Ele espia a propriedade de um objeto, para que você possa fazer algo, toda vez que obtém ou define o valor da propriedade.

RandomYang
fonte