Для чого потрібні геттери та сетери в класах ECMAScript 6?


102

Мене бентежить питання про те, що стосується геттерів та сетер у класах 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;
        }
    }
}

1
Це схоже на те, що у C #, якщо ви випадково знаєте про це.
Артуро Торрес Санчес


Гарну статтю, що пояснює це, можна знайти за адресою: coryrylan.com/blog/javascript-es6-class-syntax "У нашому класі вище є геттер і сеттер для нашого іменного властивості. Ми використовуємо умову '_' для створення резервного поля для зберігання нашої власності імені. Якщо виходити з цього пункту щоразу, коли виклик get або set це спричинить переповнення стека "... Це також говорить про зміну, яка насправді не є" приватною ", але є численні нові способи створення приватних vars в 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
S

Якщо ви хочете створити сеттери та геттери вручну, ось хороший приклад із набору coryrylan.com/blog/javascript-es6-class-syntax : set name(newName) { this._name = newName; }Отримайте:get name() { return this._name.toUpperCase(); }
Джим Дойл

48

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

Ефективно, геттери та сетери дозволяють використовувати стандартні позначення доступу до властивостей для читання і запису, зберігаючи можливість налаштування способу отримання та мутації властивості без необхідних явних методів отримання та налаштування.

У класі "Співробітник" вище, це означатиме, що ви можете отримати доступ до цього nameресурсу:

console.log(someEmployee.name);

Це буде виглядати як звичайний доступ до власності, але він фактично закликатиме toUpperCaseім'я, перш ніж повертати його. Аналогічно, роблячи це:

someEmployee.name = null;

отримав би доступ до сеттера, і він не змінив би внутрішню _nameвластивість через захисне застереження, введене в names setter.

Дивіться також загальне запитання Навіщо використовувати геттери та сетери? для отримання додаткової інформації про те, чому можливість змінити функціональність доступу членів корисна.


3

ES6, що вживають і встановлюють, мають суттєво іншу мотивацію, ніж аналогічні поняття в Java.

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

Властивості JavaBean також "відкриваються" тисячами фреймів (наприклад, у сплячому режимі) за допомогою відображення Java. Таким чином, геттери та сетери є частиною стандартного методу "опромінення" властивостей квасолі.

Геттери і сетери, будучи функціями, також мають значення, яке вони "абстрагують" реалізацією. Це може бути ВСЕ поле або обчислене ("синтетичне") значення. Тож якщо у мене є властивість bean під назвою "zipcode", вона починається як збережена рядок. Тепер припустимо, я хочу змінити це на значення, обчислене з адреси / міста / штату?

Якщо я використовую поле, цей код порушується:

      String zipcode = address.zipcode();

Але якщо я використовую геттер, це не порушує:

      String zipcode = address.getZipcode();

JavaScript не має нічого подібного до JavaBeans. Наскільки я читав, передбачуване значення GET і SET обмежене вищенаведеними "синтетичними" (обчисленими) властивостями.

Але це дещо краще, ніж java, тому що Java не дозволяє сумісно перетворити "поле" в метод, ES6 GET і SET це дозволяє.

Тобто, якщо у мене є:

       var zipcode = address.zipcode;

Якщо я зміню поштовий індекс із стандартного властивості об'єкта на геттер, тепер наведений вище код викликає функцію GET.

Зауважте, що якщо я не включив GET у визначення, це НЕ посилатиметься на метод GET zipcode. Замість цього, він буде просто призначити функцію zipcode для var.

Тому я думаю, що це кілька важливих відмінностей для розуміння між Getter і сетерами Java та JavaScript ES6 JavaScript.


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

У всякому разі, getterі setterце так само , як шпигун. Він шпигує за властивістю об'єкта, щоб ви могли щось робити щоразу, коли отримуєте чи встановлюєте значення властивості.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.