> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/b-structured/b2-objects/03-object-methods.md).

# 03. Object Methods

Методы объекта -- это функции, определенные в качестве значения ключа объекта. Основным отличием метода объекта от обычной функции заключается в том, что в этом случае `this` внутри функции ссылается на сам объект.

Существует четыре вида синтаксиса для методов объекта:

1. Функция-свойство
2. Get/Set операции свойствах
3. Метод объекта
4. Стрелочная функция

```javascript
const o = {
    functionProperty: function () { ... },
    get attributeProperty() { ... },
    set attributeProperty() { ... },
    methodProperty() { ... },
    arrowFunctionProperty: () => { ... }
}
```

## Function-property

**Свойства-функции** -- это свойство объекта, чьим значением является функция. Его можно добавить и удалить в любой момент, в том числе и явным присваиванием.

Для доступа к текущему объекту из свойства-функции используется ключевое слово `this`. Через `this` метод может не только обратиться к любому свойству объекта, но и передать куда-то ссылку на сам объект целиком. Значение `this` называется контекстом вызова и определяется каждый раз заново при каждом вызове функции. Если одну и ту же функцию запускать в контексте разных объектов, она будет получать разный `this`. Если извлечь функцию из объекта, она потеряет привязку к объекту и её `this` будет каким-то другим.

## Get/Set access properties

Это специальная разновидность синтаксиса позволяет описать свойство объекта как комбинацию двух функций:

* `get prop()`- функция вызывается на чтение свойства `prop`;
* `set prop()`- функция вызывается на призвание свойства `prop`.

Когда программа пытается получить значение свойства с методами доступа, интерпретатор вызывает метод чтения (без аргументов). Возвращаемое этим методом значение становится значением выражения обращения к свойству. Когда программа пытается записать значение в свойство, интерпретатор вызывает метод записи, передавая ему значение, находящее справа от оператора присваивания. Этот метод отвечает за «установку» значения свойства. Значение, возвращаемое методом записи, игнорируется.

В отличие от свойств с данными, свойства с методами доступа не имеют атрибута `writable`. Если свойство имеет оба метода, чтения и записи, оно доступно для чтения/записи. Если свойство имеет только метод чтения, оно доступно только для чтения. А если свойство имеет только метод записи, оно доступно только для записи (такое невозможно для свойств с данными) и попытки прочитать значение такого свойства всегда будут возвращать `undefined`.

```javascript
const name = "Anton";
const surname = "Kabysh";
const user = {
  name,
  surname,
  get fullName() {
    return `${name} ${surname}`;
  }
};

user.fullName; // Anton Kabysh
```

Основные свойства:

* Если функции сеттера нет, то свойство изменить нельзя, даже делая эту операцию.
* Если функции геттера нет, то свойство всегда будет возвращать `undefined`, хоть на попытку присваивания будет вызываться сеттер.
* Технически, `get`/`set` функции свойств так же являются методами объекта.
* Свойства с методами доступа наследуются так же, как обычные свойства с данными.

## Shorthand object methods (ES6)

В ES6 добавлены **методы объекта**, которые, по сути, являются свойствами-функциями, привязанными к объекту. Их особенности:

* Более короткий синтаксис объявления.
* Наличие в методах специального внутреннего свойства `[[HomeObject]]` (“домашний объект”), ссылающегося на объект, которому метод принадлежит.
* Доступно для обращения в методе ключевое слово `super` -- ссылка на объект прототипа.

```javascript
const user = {
  name: "Anton",
  surname: "Kabysh",
  fullName() {
    return `${this.name} ${this.surname}`;
  }
};

user.fullName(); // Anton Kabysh
```

При создании метода — он привязан к своему объекту навсегда. Технически можно даже присвоить его в переменную и запустить отдельно, но `super` продолжат работать. На `this` данное правило не распространяется, что странно.

```javascript
let parent = {
  x: "parent"
};
let child = {
  x: "child",
  papaX() {
    return super.x;
  }
};
child.papaX(); // undefined
Object.setPrototypeOf(child, parent);
child.papaX(); // 'parent'
```

## Arrow Functions

Стрелочные функции характеризуются тем, что не обладают собственным `this`, а наследуют его из лексического контекста, где они находятся. Поэтому, `this` внутри стрелочной функции привязан не к объекту, а к тому `this` в области которого этот объект определен.

```javascript
const global = this;
const c = {
  fn: () => this
};

c.fn() === global; // => true
```

* [Exposing Home Object](https://hackernoon.com/exposing-homeobject-e61061cbfe17).

## Method Calls

There are two ways to call methods in JavaScript:

* **Dynamic dispatch** (`arr.slice(1)`): property slice is searched for in the prototype chain of `arr`. Its result is called with this set to `arr`.
* **Direct call** (`Array.prototype.slice.call(arr, 1)`): `slice` is called directly with `this` set to `arr` (the first argument of `call()`).

Прямой вызов функции позволяет вызвать код функции определенный в родителе на конкретном объекте `this`, если по каким-то причинам в наследниках код этой функции был переопределен. При прямом вызове функции объекта-прототипа можно рассматривать как глобальные статические функции, поскольку их поведение чисто и зависит только от `this` и аргументов.
