Для чего нужны геттеры и сеттеры в классах ECMAScript 6?

103

Я не понимаю, в чем смысл геттеров и сеттеров в классах ECMAScript 6. Какая цель? Ниже приведен пример, о котором я говорю:

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
источник
1
Он похож на C #, если вы об этом знаете.
Артуро Торрес Санчес
Хорошую статью, объясняющую это, можно найти по адресу: coryrylan.com/blog/javascript-es6-class-syntax "В нашем классе выше у нас есть геттер и сеттер для нашего свойства name. Мы используем соглашение '_' для создания вспомогательного поля для хранения нашего свойства name. Без этого каждый раз, когда вызывается get или set, это вызовет переполнение стека "... Это также говорит о том, что переменная на самом деле не является частной, но существует множество новых способов создания частных переменных в JS классы; мне больше всего нравится использовать Typescript, но я также использовал подход Symbol
webdevinci

Ответы:

108

Эти сеттеры и геттеры позволяют напрямую использовать свойства (без использования скобок)

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

Это только для установки и получения значения свойства.

Дэвид Лаберж
источник
1
Вы имели в виду свойство, а не атрибут? Меня немного сбивает с толку
Krizzu
Хороший глаз, @Krizzu. Атрибуты существуют в JavaScript и представляют собой совершенно разные вещи, чем свойства. Ответ действительно относится к свойствам, а не к атрибутам. Я отредактировал ответ. Не думаю, что ответчик будет возражать. :)
Ray Toal
Я не совсем уверен, что это действительно такое преимущество, это как-то скрывает идею использования сеттеров / геттеров. Клиент класса может думать, что он напрямую использует свойства там, где это не подходит, но я согласен, что он придерживается принципа сокрытия информации / деталей. Возможно, если мы будем использовать это, следовательно, это упростит использование, и мне просто нужно привыкнуть к этому больше ...
Кристоф Келин
Можете ли вы передать несколько параметров в сеттер, если да, как вы его используете? @David Laberge
Vignesh S
Если вы хотите создать сеттеры и геттеры вручную, вот хороший пример из coryrylan.com/blog/javascript-es6-class-syntax Set: set name(newName) { this._name = newName; }Get:get name() { return this._name.toUpperCase(); }
Джим Дойл
48

Геттеры и сеттеры в ES6 служат той же цели, что и в других языках ... включая ES5. ES5 уже позволяет использовать геттеры и сеттеры Object.defineProperty, хотя они менее чисты и более громоздки в использовании.

Фактически, геттеры и сеттеры позволяют использовать стандартную нотацию доступа к свойствам для чтения и записи, сохраняя при этом возможность настраивать способ получения и изменения свойства без необходимости явных методов получения и установки.

В приведенном выше классе Employee это будет означать, что вы можете получить доступ к nameсвойству следующим образом:

console.log(someEmployee.name);

Это выглядело бы как обычный доступ к свойству, но на самом деле он будет вызывать toUpperCaseимя перед его возвратом. Аналогично поступаем так:

someEmployee.name = null;

будет обращаться к установщику и не будет изменять внутреннее _nameсвойство из-за предложения защиты, введенного в nameустановщике.

См. Также общий вопрос, зачем использовать геттеры и сеттеры? для получения дополнительной информации о том, почему возможность изменять функциональные возможности доступа к членам полезна.

Алексис Кинг
источник
3

У геттеров и сеттеров ES6 совершенно другая мотивация, чем у аналогичных концепций в Java.

В Java геттеры и сеттеры позволяют классу определять JavaBean. Смысл геттеров и сеттеров заключается в том, что они позволяют компоненту иметь полностью ортогональный «интерфейс» по сравнению с тем, что подразумевается общедоступными полями. Таким образом, у меня может быть поле «имя», которое НЕ является свойством JavaBean, и у меня может быть «адрес» свойства JavaBean, которое НЕ является полем.

Свойства JavaBean также «обнаруживаются» тысячами фреймворков (например, Hibernate) через отражение Java. Таким образом, геттеры и сеттеры являются частью стандартного метода «раскрытия» свойств компонента.

Геттеры и сеттеры, будучи функциями, также имеют то значение, что они «абстрагируют» реализацию. Это может быть ЛИБО поле или вычисленное («синтетическое») значение. Итак, если у меня есть свойство bean-компонента под названием «zipcode», оно начинается как сохраненная строка. Теперь предположим, что я хочу изменить его на значение, вычисленное из адреса / города / штата?

Если я использую поле, этот код ломается:

      String zipcode = address.zipcode();

Но если я использую геттер, это не сломается:

      String zipcode = address.getZipcode();

В JavaScript нет ничего похожего на JavaBeans. Насколько я читал, предполагаемое значение GET и SET ограничено вышеупомянутыми «синтетическими» (вычисленными) свойствами.

Но это несколько лучше, чем java в том, что, хотя Java не позволяет вам совместимо преобразовывать «поле» в метод, ES6 GET и SET позволяют это.

То есть, если у меня есть:

       var zipcode = address.zipcode;

Если я изменю zipcode из стандартного свойства объекта на геттер, то приведенный выше код теперь вызывает функцию GET.

Обратите внимание: если бы я не включил GET в определение, это НЕ будет вызывать метод GET почтового индекса. Вместо этого он просто назначит функцию zipcode переменной.

Итак, я думаю, что это некоторые важные различия для понимания между методами получения и установки Java и JavaScript ES6.

DaBlick
источник
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

В любом случае, getterи setterэто как шпион. Он отслеживает свойство объекта, так что вы можете что-то делать каждый раз, когда получаете или устанавливаете значение свойства.

RandomYang
источник