# Context (this)

Поведение ключевого слова `this` в JavaScript несколько отличается от остальных языков. Имеются также различия при использовании `this` в [строгом](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) и нестрогом режиме.

В большинстве случаев значение `this` определяется тем, каким образом вызвана функция. Значение `this`не может быть установлено путем присваивания во время исполнения кода и может иметь разное значение при каждом вызове функции. В ES5 представлен метод [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind), чтобы [определить значение ключевого слова this независимо от того, как вызвана функция](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this$translate?tolocale=ru#The_bind_method). Также в ECMAScript 2015 представлены [стрелочные функции](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions), this которых привязан к окружению, в котором была создана стрелочная функция.

## Глобальный контекст <a href="#globalnyi_kontekst" id="globalnyi_kontekst"></a>

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

```javascript
console.log(this.document === document); // true

// В браузерах, объект window также является глобальным:
console.log(this === window); // true

this.a = 37;
console.log(window.a); // 37
```

## В контексте функции <a href="#v_kontekste_funkcii" id="v_kontekste_funkcii"></a>

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

### Простой вызов <a href="#prostoi_vyzov" id="prostoi_vyzov"></a>

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

```javascript
function f1(){
  return this;
}
// В браузере
f1() === window; // window глобальный объект в браузере
```

В строгом режиме, значение `this` остается тем значением, которое было установлено в контексте исполнения. Если такое значение не определено, оно остается undefined.

```javascript
function f2(){
  "use strict"; // see strict mode
  return this;
}

f2() === undefined;
```

Итак, в строгом режиме, если this не определено, оно остается не определено.

Для того, чтобы передать значение this от одного контекста другому, необходимо использовать [call](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call) или [apply](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/apply).

### Стрелочные функции <a href="#strelochnye_funkcii" id="strelochnye_funkcii"></a>

В [стрелочных функциях](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions) `this` привязан к окружению, в котором была создана функция. В глобальной области видимости `this` будет указывать на глобальный объект.

```javascript
var globalObject = this;
var foo = (() => this);
console.log(foo() === globalObject); // true
```

Неважно, как функция `foo()`будет вызвана, ее this будет указывать на глобальный объект.`this` будет сохранять свое значение, даже если функция `foo()`будет вызвана как метод объекта (что в обычных функциях связывает `this` с объектом вызова) или с использованием методов `call`,`apply ,`или`bind`:

```javascript
// Вызов функции как метода объекта
var obj = {foo: foo};
console.log(obj.foo() === globalObject); // true

// Попытка установить this с помощью call
console.log(foo.call(obj) === globalObject); // true

// Попытка установить this с помощью bind
foo = foo.bind(obj);
console.log(foo() === globalObject); // true
```

Независимо от этого, `this` функции `foo()`имеет тоже значение, что и при создании функции (глобальный объект в примере выше). То же самое касается стрелочных функций, созданных внутри других функций: их `this` будет привязан к окружению.

```javascript
// Создаем объект obj с методом bar, который возвращает функцию
// которая возвращает свой this. Возвращаемая функция создана
// как стрелочная функция, таким образом ее this замкнут 
// на this функции, в которой она создана. 
var obj = { bar : function() {
                    var x = (() => this);
                    return x;
                  }
          };

// Вызываем bar как метод объекта obj, устанавливая его this на obj
// Присваиваем ссылку возвращаемой функции fn
var fn = obj.bar();

// Вызываем fn без установки this, что в обычных функциях указывало бы
// на глобальный объект или undefined в строгом режиме.
console.log(fn() === obj); // true
```

В примере выше, функция (назовем ее анонимной функцией A), присвоенная `obj.bar` , возвращает другую функцию (назовем ее анонимной функцией B), которая создана как стрелочная функция. В результате вызова функции A, `this функции B замкнут на this,` принадлежащий `obj.bar` (функции A). `this` функции B, всегда будет иметь то значение, которое он получил при создании. В примере выше `this функции B` указывает на `this функции A, который указывает на` obj, таким образом this будет указывать на `obj` даже когда будет вызван методом, который в нормальных условиях устанавливал значение this равным `undefined или глобальному объекту` ( или любым другим методом, как в предыдущих примерах).

### В методе объекта <a href="#v_metode_obekta" id="v_metode_obekta"></a>

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

В следующем примере, когда вызвано свойство `o.f()`, внутри функции `this` привязано к объекту `o.`

```javascript
var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};

console.log(o.f()); // logs 37
```

Необходимо отметить, что на поведение this совсем не влияет то, как или где была определена функция. В предыдущем примере мы определили функцию внутри свойства `f` во время определения объекта `o`. Однако мы могли бы также просто определить сначала функцию, а затем закрепить ее за за свойством `o.f`. В этом случае поведение this не изменится:

```javascript
var o = {prop: 37};

function independent() {
  return this.prop;
}

o.f = independent;

console.log(o.f()); // logs 37
```

Эти примеры показывают, что имеет значение только то, что функция была вызвана из свойства `f` объекта `o`.

Аналогично, привязывание `this` обуславлавливается наличием ближайшей ссылки на объект или свойство. В следующем примере, когда мы вызываем функцию, мы обращаемся к ней как к методу `g` объекта `o.b`. На этот раз во время выполнения `this,` что находится внутри функции, будет ссылаться на `o.b`. Тот факт, что объект является членом объекта `o` , не имеет значения; важна только ближайшая ссылка.

```javascript
o.b = {g: independent, prop: 42};
console.log(o.b.g()); // logs 42
```

#### `this`в цепочке object's prototype <a href="#this_v_cepochke_objects_prototype" id="this_v_cepochke_objects_prototype"></a>

Это же представление справедливо и для методов, определенных где-либо в цепочке object's prototype. Если метод находится в цепочке прототипов, то this ссылается на объект, на котором был вызван метод, т.е. так, словно метод является методом самого объекта, а не прототипа.

```javascript
var o = {f:function(){ return this.a + this.b; }};
var p = Object.create(o);
p.a = 1;
p.b = 4;

console.log(p.f()); // 5
```

В этом примере, объект, которому присвоена переменная `p,` не имеет собственного свойства `f`, а наследует это свойство от своего прототипа. Однако совершенно неважно, что поиск свойства f в конце концов обнаружит его на объекте `o`. Поскольку поиск начался с `p.f`, то и свойство `this` внутри функции `f`будет ссылаться на объект`p`. Таким образом, если `f` вызывается как метод `p`, то и `this` относится к `p`. Это полезная особенность прототипного наследования JS.

#### `this`с геттерами/сеттерами <a href="#this_s_getteramisetterami" id="this_s_getteramisetterami"></a>

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

```javascript
function modulus(){
  return Math.sqrt(this.re * this.re + this.im * this.im);
}

var o = {
  re: 1,
  im: -1,
  get phase(){
    return Math.atan2(this.im, this.re);
  }
};

Object.defineProperty(o, 'modulus', {
    get: modulus, enumerable:true, configurable:true});

console.log(o.phase, o.modulus); // logs -0.78 1.4142
```

### В конструкторе <a href="#v_konstruktore" id="v_konstruktore"></a>

Когда функция используется как конструктор (с ключевым словом [`new`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new)), `this` связано с создаваемым новым объектом.

Примечание: по умолчанию конструктор возвращает объект, к которому ссылается `this`, но он может вернуть и другой объект (если возвращаемое значение не является объектом, тогда будет возвращен объект с `this`).

```javascript
/*
 * Контруктор работает таким образом:
 *
 * function MyConstructor(){
 *   // фактический код, составляющий тело функции.  
 *   // создание свойств с |this| по 
 *   // желанию, определяя их. например,
 *   this.fum = "nom";
 *   // и т.д..
 *
 *   // Если функция возвращает выражение,
 *   // возвращающее объект, этот объект будет 
 *   // результатом  выражения|new|.  В обратном случае,
 *   // результат выражения - объект
 *   // в данный момент привязанный к |this|
 *   // (т.е. наиболее часто встречающийся случай).
 * }
 */

function C(){
  this.a = 37;
}

var o = new C();
console.log(o.a); // logs 37


function C2(){
  this.a = 37;
  return {a:38};
}

o = new C2();
console.log(o.a); // logs 38
```

В последнем примере (`C2`) из-за того, что конструктор вернул объект, новый объект, к которому было привязано `this,` был просто отброшен. (Это фактически делает выражение "`this.a = 37;`" "мертвым" кодом. Он не является буквально нерабочим, так как он выполняется, но он может быть изъят без каких-либо внешних эффектов.)

### `call`и`apply` <a href="#call_i_apply" id="call_i_apply"></a>

Когда в теле функции используется ключевое слово `this`, его значение может быть привязано к конкретному объекту в вызове при помощи методов [`call`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call) или[`apply`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply), которые наследуются всеми функциями от `Function.prototype`.

```javascript
function add(c, d){
  return this.a + this.b + c + d;
}

var o = {a:1, b:3};

// Первый параметр - это объект, который следует использовать как
// 'this', последующие параметры передаются 
// как аргументы при вызове функции
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16

// Первый параметр - объект, который следует использовать как
// 'this', второй параметр - массив, 
// элементы которого используются как аргументы при вызове функции
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
```

Необходимо отметить, что если методам `call` и `apply` передается значение с `this,` которое не является при этом объектом, будет предпринята попытка конвертировать значение в объект, используя внутреннюю операцию `ToObject`. Если переданное значение является примитивным типом, таким как `7` или `'foo'`, оно будет преобразовано в объект с использованием родственного конструктора, так примитив `7` преобразовывается в объект через `new Number(7),` а строка `'foo'` в объект через `new String('foo')` и т.д.

```javascript
function bar() {
  console.log(Object.prototype.toString.call(this));
}

bar.call(7); // [object Number]
```

### Метод `bind` <a href="#metod_bind" id="metod_bind"></a>

ECMAScript 5 ввел [`Function.prototype.bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind). Вызов `f.bind(someObject)`создает новую функцию с тем же телом и областью видимости, что и `f`, но там, где находится `this` в исходной функции, в новой функции существует постоянная привязка к первому аргументу метода `bind`несмотря на то, как используется данная функция.

```javascript
function f(){
  return this.a;
}

var g = f.bind({a:"azerty"});
console.log(g()); // azerty

var o = {a:37, f:f, g:g};
console.log(o.f(), o.g()); // 37, azerty
```

### Как обработчик событий DOM <a href="#kak_obrabotchik_sobytii_dom" id="kak_obrabotchik_sobytii_dom"></a>

Когда функция используется как обработчик событий, `this` присваивается элементу, с которого начинается событие (некоторые браузеры не следуют этому соглашению для слушателей, добавленных динамически с помощью всех методов кроме`addEventListener`).

```javascript
// When called as a listener, turns the related element blue
function bluify(e){
  // Always true
  console.log(this === e.currentTarget); 
  // true when currentTarget and target are the same object
  console.log(this === e.target);
  this.style.backgroundColor = '#A5D9F3';
}

// Get a list of every element in the document
var elements = document.getElementsByTagName('*');

// Add bluify as a click listener so when the
// element is clicked on, it turns blue
for(var i=0 ; i<elements.length ; i++){
  elements[i].addEventListener('click', bluify, false);
}
```

### В инлайновом обработчике событий <a href="#v_inlainovom_obrabotchike_sobytii" id="v_inlainovom_obrabotchike_sobytii"></a>

Когда код вызван из инлайнового обработчика, this указывает на DOM-элемент, в котором расположен код события:

```
<button onclick="alert(this.tagName.toLowerCase());">
  Показать this
</button>
```

Код выше выведет '`button`'. Следует отметить, this будет указывать на DOM элемент только во внешних (не вложенных) функциях:

```
<button onclick="alert((function(){return this}()));">
  Показать вложенный this
</button>
```

В этом случае `this` вложеной функции не будет установлен, так что будет возвращен global/window объект.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://andersenlab.gitbook.io/javascript/advanced-javascript/context-this.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
