JavaScript | get set object this | Рабочий this в одном объекте с геттером и сеттером

JavaScript | get set object this | Рабочий this в одном объекте с геттером и сеттером

Как создать объект с вычисляемым свойством? Как использовать ключевое слово this внутри одного объекта? Как сделать так, чтобы ЗНАЧЕНИЕ по КЛЮЧУ (элемента/свойства) в объекте автоматически высчитывалось на основании других ЗНАЧЕНИЙ у других КЛЮЧЕЙ?

 

Оглавление

  1. Добавляем get в объект
  2. Добавляем set в объект

 

В чём тут проблема?

В обычном объекте мы не можем сослаться на другие значения. Есть объект:

var obj = {
   x:2,
   y:3,
   z:4
}

Вывод объекта obj в консоль браузера:

Объект 3 свойства - JavaScript
Объект 3 свойства — JavaScript

Теперь мы хотим добавить свойство с ключом xyz, в значении которого мы хотим видеть сумму всех трёх значений, по аналогичным ключам. Сначала нам хочется сделать как-то так:

var obj = {
   x:2,
   y:3,
   z:4,
   xyz: this.x + this.y + this.z
}

Не сработало. Получим NaN вместо нужных данных:

NaN вместо вычисления значения в объекте - JavaScript
NaN вместо вычисления значения в объекте — JavaScript

Даже если сослаться на одно свойство объекта:

var obj = {
   x:2,
   y:3,
   z:4,
   xyz: this.x
}

Всё равно НЕ получим, что хотим. КЛЮЧ «xyz» в этом случае вернёт undefined

Попытка обратиться к другому значению внутри одного объекта - JavaScript
Попытка обратиться к другому значению внутри одного объекта — JavaScript

Как быть?

Нужно решать проблему при помощи геттеров и сеттеровget и set соответственно. С их помощью появится возможность ссылаться на другие ключи этого же объекта при помощи this.

 

Как ПОЛУЧАТЬ вычисляемое значение? — Добавляем get в объект

Синтаксис такой. Мы пишем слово get, ставим пробел, а затем пишем функцию, которая будет вычислять (возвращать) нам нужное значение. Суть в том, что название функции будет являться ключом — в нашем случае xyz

var obj = {
   x:2,
   y:3,
   z:4,
   get xyz() { return this.x + this.y + this.z }
}

Вводим в консоль браузера:

Вычисляемое значение в объекте - JavaScript
Вычисляемое значение в объекте — JavaScript

Мы обратились к объекту obj и у ключа xyz мы увидели троеточие в круглых скобках. Таким образом браузер намекнул нам, что внутри будет лежать вычисляемое значение. Давайте нажмём на три точки:

Нажали на троеточие в объекте JavaScript в консоли браузера
Нажали на троеточие в объекте JavaScript в консоли браузера

В результате мы получили сумму трёх элементов (2 + 3 + 4 = 9)

 

Теперь обратимся к объекту obj по ключу xyz

ключ xyz вычислил 9 - JavaScript
ключ xyz вычислил 9 — JavaScript

Если сейчас мы изменим другие свойства, то автоматически изменится вычисляемое значение по ключу xyz

obj.x = 10
obj.y = 20
obj.z = 30

Выводим объект. Нажимаем на троеточие.

Обновили объект obj - JavaScript
Обновили объект obj — JavaScript

Обращаемся по ключу xyz

obj.xyz

Результат 10 + 20 + 30 = 60

ключ xyz вычислил 60 - JavaScript
ключ xyz вычислил 60 — JavaScript

Как УСТАНАВЛИВАТЬ в вычисляемое значение? — Добавляем set в объект

Мы разобрали, как ПОЛУЧАТЬ вычисляемое значение. Но мы также можем изменять вычисляемое значение на своё собственное. Допишем наш объект. Добавим в него сеттер — set:

var obj = {
   x:2,
   y:3,
   z:4,
   get xyz() { return this.x + this.y + this.z },
   set xyz(value) { this.xyz = value}
}

По логике хочется написать именно так — set xyz(value) { this.xyz = value} . Мы, как бы, хотим передать в сеттер некоторое значение, которое по итогу должно оставаться под ключом xyz. Такая запись породит нескончаемый цикл т. к. присваивание value к this.xyz по сути будет снова и снова пробрасывать одно и то же значение в функцию-сеттер. Конца этому не будет — стек вызовов переполнится. Будет ошибка.

 

Uncaught RangeError- Maximum call stack size exceeded - JavaScript
Uncaught RangeError- Maximum call stack size exceeded — JavaScript

Как решить проблему? Мы будем передавать нужное значение в сеттер xyz , но внутри будем изменять другие свойства этого же объекта. Какие? Да те, которые формируют геттер.

var obj = {
   x:2,
   y:3,
   z:4,
   get xyz() { return this.x + this.y + this.z },
   set xyz(value) { 
      this.x = value
      this.y = 0
      this.z = 0
   }
}

В результате для ключа «x» будет присвоено переданное в сеттер значение, а ключам «y» и «z» будут присвоены нули.

Правильный сеттер для вычисляемого значения - JavaScript
Правильный сеттер для вычисляемого значения — JavaScript

Проверим на практике. Установим для ключа «xyz» значение 77.

obj.xyz = 77
ключу xyz присвоили 77 - JavaScript
ключу xyz присвоили 77 — JavaScript

Мы установили для ключа «xyz» значение 77, хотя для этого пришлось изменить другие значения. Логика работы сеттера зависит от вашей задачи, которую будет решать алгоритм. Это всего лишь частный случай для понимания работы set.

 

Информационные ссылки

JavaScript | Объекты (Object)

Стандарт ECMAScript — Раздел «15.4 Method Definitions» — https://tc39.es/ecma262/#prod-MethodDefinition

Официальный документ — Тип данных Object — https://tc39.es/ecma262/#sec-object-type

Официальный документ — Объекты Object  — https://tc39.es/ecma262/#sec-object-objects