Do czego służą metody pobierające i ustawiające w klasach ECMAScript 6?

103

Jestem zdezorientowany co do celu getters i setters w klasach ECMAScript 6. Co jest celem? Poniżej przykład, do którego się odwołuję:

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
źródło
1
Jest podobny do tych w C #, jeśli wiesz o tym.
Arturo Torres Sánchez
Dobry artykuł wyjaśniający to właśnie można znaleźć pod adresem: coryrylan.com/blog/javascript-es6-class-syntax "W naszej powyższej klasie mamy metodę pobierającą i ustawiającą dla naszej właściwości name. Używamy konwencji„ _ ", aby utworzyć pole zapasowe aby przechowywać naszą właściwość name. Bez tego za każdym razem, gdy wywoływana jest funkcja get lub set, spowodowałoby to przepełnienie stosu. Klasy JS; moim ulubionym jest po prostu używanie Typescriptu, ale użyłem też podejścia Symbol
webdevinci

Odpowiedzi:

108

Te metody ustawiające i pobierające umożliwiają bezpośrednie użycie właściwości (bez używania nawiasów)

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

Służy to tylko do ustawienia i uzyskania wartości właściwości.

David Laberge
źródło
1
Czy chodziło Ci o własność zamiast atrybutu? Trochę mylące dla mnie
Krizzu
Dobre oko, @Krizzu. Atrybuty istnieją w JavaScript i są zupełnie innymi rzeczami niż właściwości. Odpowiedź rzeczywiście odnosi się do właściwości, a nie atrybutów. Zmieniłem odpowiedź. Nie sądzę, by osoba odpowiadająca miała coś przeciwko. :)
Ray Toal
Nie jestem do końca pewien, czy to naprawdę jest taka zaleta, w jakiś sposób ukrywa to pojęcie używania seterów / getterów. Klient klasy może pomyśleć, że bezpośrednio korzysta z właściwości, gdzie nie jest to odpowiednie, ale zgadzam się, że przestrzega zasady ukrywania informacji / szczegółów. Może jeśli będziemy tego używać w konsekwencji, ułatwi to użytkowanie i po prostu muszę się do tego bardziej przyzwyczaić ...
Christof Kälin
Czy możesz przekazać wiele parametrów w programie ustawiającym, jeśli tak, jak go używać? @David Laberge
Vignesh S
Jeśli chcesz ręcznie tworzyć setery i gettery, oto dobry przykład z coryrylan.com/blog/javascript-es6-class-syntax Zestaw: set name(newName) { this._name = newName; }Get:get name() { return this._name.toUpperCase(); }
Jim Doyle
48

Metody pobierające i ustawiające w ES6 służą temu samemu celowi, co w innych językach ... w tym w ES5. ES5 już pozwala na metody pobierające i ustawiające Object.defineProperty, chociaż są one mniej czyste i bardziej kłopotliwe w użyciu.

W efekcie metody pobierające i ustawiające umożliwiają używanie standardowej notacji dostępu do właściwości do odczytów i zapisów, przy jednoczesnym zachowaniu możliwości dostosowywania sposobu pobierania i mutowania właściwości bez konieczności stosowania jawnych metod pobierających i ustawiających.

W powyższej klasie Pracownik oznaczałoby to, że możesz uzyskać dostęp do usługi w namenastępujący sposób:

console.log(someEmployee.name);

Byłoby to wyglądać jak normalny dostęp do nieruchomości, ale to właściwie nazwać toUpperCaseimienia przed wpuszczeniem go. Podobnie, robiąc to:

someEmployee.name = null;

uzyskałby dostęp do settera i nie zmodyfikowałby wewnętrznej _namewłaściwości z powodu klauzuli guard wprowadzonej w nameseterze.

Zobacz także ogólne pytanie Dlaczego warto używać metod pobierających i ustawiających? aby uzyskać więcej informacji o tym, dlaczego możliwość modyfikowania funkcjonalności dostępu członków jest przydatna.

Alexis King
źródło
3

Programy pobierające i ustawiające w ES6 mają zasadniczo inną motywację niż podobne koncepcje w Javie.

W Javie metody pobierające i ustawiające pozwalają klasie na definiowanie komponentów JavaBean. Celem metod pobierających i ustawiających jest to, że pozwalają one fasoli mieć całkowicie ortogonalny „interfejs” w porównaniu z polami publicznymi. Więc mogę mieć pole „nazwa”, które NIE jest właściwością JavaBean i mogę mieć „adres” właściwości JavaBean, który NIE jest polem.

Właściwości JavaBean są również „wykrywalne” przez tysiące frameworków (na przykład Hibernate) poprzez odbicie języka Java. Zatem metody pobierające i ustawiające są częścią standardowej metody „ujawniania” właściwości fasoli.

Metody pobierające i ustawiające, będąc funkcjami, mają również tę wartość, że „abstraktują” implementację. Może to być ALBO pole lub wartość obliczona („syntetyczna”). Więc jeśli mam właściwość fasoli o nazwie „kod pocztowy”, która zaczyna się jako przechowywany ciąg. A teraz przypuśćmy, że chcę zmienić to na wartość obliczoną na podstawie adresu / miasta / stanu?

Jeśli używam pola, ten kod się psuje:

      String zipcode = address.zipcode();

Ale jeśli używam gettera, to się nie psuje:

      String zipcode = address.getZipcode();

JavaScript nie ma nic takiego jak JavaBeans. O ile czytałem, zamierzona wartość GET i SET jest ograniczona do wspomnianych powyżej właściwości „syntetycznych” (obliczonych).

Ale jest nieco lepszy niż java, ponieważ podczas gdy Java nie pozwala na kompatybilną konwersję "pola" na metodę, ES6 GET i SET na to pozwala.

To znaczy, jeśli mam:

       var zipcode = address.zipcode;

Jeśli zmienię kod pocztowy ze standardowej właściwości obiektu na getter, powyższy kod wywoła teraz funkcję GET.

Zwróć uwagę, że jeśli nie uwzględniłem GET w definicji, NIE wywołałoby to metody GET kodu pocztowego. Zamiast tego po prostu przypisałby kod pocztowy funkcji do zmiennej.

Myślę więc, że są to ważne różnice, które należy odróżnić między metodami pobierającymi i ustawiającymi w języku Java i JavaScript w ES6.

DaBlick
źródło
1
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

W każdym razie getteri setterjest jak szpieg. Szpieguje właściwość obiektu, dzięki czemu możesz coś zrobić za każdym razem, gdy otrzymasz lub ustawisz wartość tej właściwości.

RandomYang
źródło