this
Базовая поддержка Широко доступно
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и в разных версиях браузеров. Она доступна во всех браузерах с июля 2015 года.
Ключевое слово this указывает на контекст, в котором должен выполняться фрагмент кода, например тело функции. Чаще всего оно используется в методах объектов, где this указывает на объект, к которому относится метод, что позволяет повторно использовать один и тот же метод с разными объектами.
Значение this в JavaScript зависит от способа вызова функции (привязки во время выполнения), а не от способа её определения. Если обычная функция вызывается как метод объекта (obj.method()), this указывает на этот объект. Если функция вызывается отдельно (не как метод объекта: func()), this обычно указывает на глобальный объект (в нестрогом режиме) или на undefined (в строгом режиме). Метод Function.prototype.bind() позволяет создать функцию, привязка this которой не меняется, а методы Function.prototype.apply() и Function.prototype.call() позволяют задать значение this для конкретного вызова.
Стрелочные функции обрабатывают this иначе: они наследуют this из родительской области видимости на момент своего определения. Благодаря этому стрелочные функции особенно полезны для функций обратного вызова и сохранения контекста. Однако у стрелочных функций нет собственной привязки this. Поэтому для них нельзя задать значение this с помощью методов bind(), apply() или call(), и оно не указывает на текущий объект в методах объектов.
Попробуйте
const test = {
prop: 42,
func() {
return this.prop;
},
};
console.log(test.func());
// Expected output: 42
Синтаксис
this
Значение
В нестрогом режиме this всегда является ссылкой на объект. В строгом режиме оно может иметь любое значение. Подробнее о том, как определяется это значение, см. в описании ниже.
Описание
Значение this зависит от контекста, в котором оно используется: функции, класса или глобальной области.
Контекст функции
Внутри функции значение this зависит от способа вызова функции. Представьте this как скрытый параметр функции — подобно параметрам, объявленным в определении функции, this является привязкой, которую язык создаёт для вас при вычислении тела функции.
Для обычной функции (не стрелочной, не привязанной и т. д.) значением this является объект, у которого вызывается функция. Иными словами, если вызов функции имеет вид obj.f(), то this указывает на obj. Например:
function getThis() {
return this;
}
const obj1 = { name: "obj1" };
const obj2 = { name: "obj2" };
obj1.getThis = getThis;
obj2.getThis = getThis;
console.log(obj1.getThis()); // { name: 'obj1', getThis: [Function: getThis] }
console.log(obj2.getThis()); // { name: 'obj2', getThis: [Function: getThis] }
Обратите внимание: функция одна и та же, но значение this различается в зависимости от способа её вызова. Это похоже на работу параметров функций.
Значением this является не объект, которому функция принадлежит как собственное свойство, а объект, используемый для вызова функции. Это можно проверить, вызвав метод объекта из цепочки прототипов.
const obj3 = {
__proto__: obj1,
name: "obj3",
};
console.log(obj3.getThis()); // { name: 'obj3' }
Значение this всегда меняется в зависимости от способа вызова функции, даже если при создании функция была определена в объекте:
const obj4 = {
name: "obj4",
getThis() {
return this;
},
};
const obj5 = { name: "obj5" };
obj5.getThis = obj4.getThis;
console.log(obj5.getThis()); // { name: 'obj5', getThis: [Function: getThis] }
Если значение, у которого вызывается метод, является примитивом, this также будет примитивным значением — но только если функция работает в строгом режиме.
function getThisStrict() {
"use strict"; // Enter strict mode
return this;
}
// Only for demonstration — you should not mutate built-in prototypes
Number.prototype.getThisStrict = getThisStrict;
console.log(typeof (1).getThisStrict()); // "number"
Если функция вызывается без объекта, у которого её можно было бы вызвать, this будет равно undefined — но только если функция работает в строгом режиме.
console.log(typeof getThisStrict()); // "undefined"
В нестрогом режиме специальный процесс, называемый подстановкой this, гарантирует, что значение this всегда будет объектом. Это означает следующее:
- Если функция вызывается со значением
this, равнымundefinedилиnull, вместоthisподставляетсяglobalThis. - Если функция вызывается со значением
this, равным примитивному значению, вместоthisподставляется объект-обёртка этого примитивного значения.
function getThis() {
return this;
}
// Only for demonstration — you should not mutate built-in prototypes
Number.prototype.getThis = getThis;
console.log(typeof (1).getThis()); // "object"
console.log(getThis() === globalThis); // true
При обычных вызовах функции значение this неявно передаётся как параметр через префикс функции (часть до точки). Можно также явно задать значение this с помощью методов Function.prototype.call(), Function.prototype.apply() или Reflect.apply(). С помощью Function.prototype.bind() можно создать новую функцию с определённым значением this, которое не меняется независимо от способа вызова функции. Если функция нестрогая, при использовании этих методов по-прежнему применяются описанные выше правила подстановки this.
Функции обратного вызова
Если функция передаётся в качестве функции обратного вызова, значение this зависит от способа вызова этой функции, который определяется разработчиком API. Обычно функции обратного вызова вызываются со значением this, равным undefined (то есть вызываются напрямую, без привязки к какому-либо объекту). Это означает, что для нестрогой функции значение this будет равно глобальному объекту (globalThis). Так работают итерационные методы массивов, конструктор Promise() и т. д.
function logThis() {
"use strict";
console.log(this);
}
[1, 2, 3].forEach(logThis); // undefined, undefined, undefined
Некоторые API позволяют задать значение this для вызовов функции обратного вызова. Например, все итерационные методы массивов и связанные с ними методы, такие как Set.prototype.forEach(), принимают необязательный параметр thisArg.
[1, 2, 3].forEach(logThis, { name: "obj" });
// { name: 'obj' }, { name: 'obj' }, { name: 'obj' }
Иногда функция обратного вызова вызывается со значением this, отличным от undefined. Например, параметр reviver метода JSON.parse() и параметр replacer метода JSON.stringify() вызываются со значением this, равным объекту, которому принадлежит разбираемое или сериализуемое свойство.
Стрелочные функции
В стрелочных функциях this сохраняет значение this из окружающего лексического контекста. Иными словами, при вычислении тела стрелочной функции язык не создаёт новую привязку this.
Например, в глобальном коде this всегда равно globalThis независимо от строгости режима, благодаря привязке в глобальном контексте:
const globalObject = this; const foo = () => this; console.log(foo() === globalObject); // true
Стрелочные функции создают замыкание над значением this окружающей области видимости. Это означает, что стрелочные функции ведут себя так, как будто они «автоматически привязаны»: независимо от способа вызова, this привязано к значению, которое оно имело при создании функции (в примере выше — к глобальному объекту). То же относится к стрелочным функциям, созданным внутри других функций: их this сохраняет значение из окружающего лексического контекста. См. пример ниже.
Кроме того, при вызове стрелочных функций с помощью call(), bind() или apply() параметр thisArg игнорируется. Однако с помощью этих методов по-прежнему можно передавать другие аргументы.
const obj = { name: "obj" };
// Attempt to set this using call
console.log(foo.call(obj) === globalObject); // true
// Attempt to set this using bind
const boundFoo = foo.bind(obj);
console.log(boundFoo() === globalObject); // true
Конструкторы
Когда функция используется как конструктор (с ключевым словом new), её this привязывается к создаваемому новому объекту независимо от того, у какого объекта вызывается функция-конструктор. Значение this становится значением выражения new, если только конструктор не возвращает другое непримитивное значение.
function C() {
this.a = 37;
}
let o = new C();
console.log(o.a); // 37
function C2() {
this.a = 37;
return { a: 38 };
}
o = new C2();
console.log(o.a); // 38
Во втором примере (C2), поскольку во время создания объекта был возвращён объект, новый объект, к которому было привязано this, отбрасывается. (По сути, это делает инструкцию this.a = 37; мёртвым кодом. Она не совсем мёртвая, поскольку выполняется, но её можно удалить без каких-либо внешних последствий.)
super
Если функция вызывается в форме super.method(), значение this внутри функции method совпадает со значением this вокруг вызова super.method() и, как правило, не равно объекту, на который указывает super. Это связано с тем, что super.method — не обращение к члену объекта, как в приведённых выше примерах, а специальный синтаксис с другими правилами привязки. Примеры см. в разделе о ссылке super.
Контекст класса
Класс можно разделить на два контекста: статический и экземпляра. Конструкторы, методы и инициализаторы полей экземпляра (публичных или приватных) относятся к контексту экземпляра. Статические методы, инициализаторы статических полей и блоки статической инициализации относятся к статическому контексту. Значение this в каждом контексте различается.
Конструкторы классов всегда вызываются с new, поэтому они ведут себя так же, как конструкторы-функции: значением this является создаваемый новый экземпляр. Методы классов работают так же, как методы в литералах объектов: значением this является объект, у которого был вызван метод. Если метод не передан другому объекту, this обычно является экземпляром класса.
Статические методы не являются свойствами this. Они являются свойствами самого класса. Поэтому обычно их вызывают у класса, а this имеет значение класса (или подкласса). Блоки статической инициализации также выполняются со значением this, равным текущему классу.
Инициализаторы полей также вычисляются в контексте класса. Поля экземпляра вычисляются со значением this, равным создаваемому экземпляру. Статические поля вычисляются со значением this, равным текущему классу. Поэтому стрелочные функции в инициализаторах полей привязываются к экземпляру для полей экземпляра и к классу для статических полей.
class C {
instanceField = this;
static staticField = this;
}
const c = new C();
console.log(c.instanceField === c); // true
console.log(C.staticField === C); // true
Конструкторы производных классов
В отличие от конструкторов базовых классов, конструкторы производных классов изначально не имеют привязки this. Вызов super() создаёт привязку this в конструкторе и, по сути, приводит к вычислению следующей строки кода, где Base — базовый класс:
this = new Base();
Предупреждение: Обращение к this до вызова super() приведёт к ошибке.
Производные классы не должны возвращать значение до вызова super(), за исключением случаев, когда конструктор возвращает объект (и значение this переопределяется) или у класса вообще нет конструктора.
class Base {}
class Good extends Base {}
class AlsoGood extends Base {
constructor() {
return { a: 5 };
}
}
class Bad extends Base {
constructor() {}
}
new Good();
new AlsoGood();
new Bad(); // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
Глобальный контекст
В глобальном контексте выполнения (вне любых функций и классов; он может находиться внутри блоков или стрелочных функций, определённых в глобальной области видимости) значение this зависит от контекста выполнения скрипта. Как и в случае с функциями обратного вызова, значение this определяется средой выполнения (вызывающей стороной).
На верхнем уровне скрипта this указывает на globalThis независимо от того, используется ли строгий режим. Обычно это то же самое, что и глобальный объект. Например, если исходный код помещён в элемент HTML <script> и выполняется как скрипт, this === window.
Примечание: globalThis обычно соответствует понятию глобального объекта (то есть добавление свойств в globalThis делает их глобальными переменными). Так происходит в браузерах и Node, но хост-среды могут предоставлять для globalThis другое значение, не связанное с глобальным объектом.
// In web browsers, the window object is also the global object: console.log(this === window); // true this.b = "MDN"; console.log(window.b); // "MDN" console.log(b); // "MDN"
Если исходный код загружается как модуль (в HTML для этого нужно добавить type="module" к тегу <script>), на верхнем уровне this всегда равно undefined.
Если исходный код выполняется с помощью eval(), this совпадает с окружающим контекстом при прямом eval или равно globalThis (как при запуске в отдельном глобальном скрипте) при косвенном eval.
function test() {
// Direct eval
console.log(eval("this") === this);
// Indirect eval, non-strict
console.log(eval?.("this") === globalThis);
// Indirect eval, strict
console.log(eval?.("'use strict'; this") === globalThis);
}
test.call({ name: "obj" }); // Logs 3 "true"
Обратите внимание: некоторый исходный код, который выглядит как глобальная область видимости, на самом деле при выполнении оборачивается в функцию. Например, модули Node.js CommonJS оборачиваются в функцию и выполняются со значением this, равным module.exports. Атрибуты обработчиков событий выполняются со значением this, равным элементу, к которому они прикреплены.
Литералы объектов не создают область видимости this — её создают только определённые внутри объекта функции (методы). Использование this в литерале объекта наследует значение из окружающей области видимости.
const obj = {
a: this,
};
console.log(obj.a === window); // true
Примеры
this в контексте функций
Значение параметра this зависит от способа вызова функции, а не от способа её определения.
// An object can be passed as the first argument to 'call'
// or 'apply' and 'this' will be bound to it.
const obj = { a: "Custom" };
// Variables declared with var become properties of 'globalThis'.
var a = "Global";
function whatsThis() {
return this.a; // 'this' depends on how the function is called
}
whatsThis(); // 'Global'; the 'this' parameter defaults to 'globalThis' in non–strict mode
obj.whatsThis = whatsThis;
obj.whatsThis(); // 'Custom'; the 'this' parameter is bound to obj
С помощью call() и apply() можно передать значение this как явный параметр.
function add(c, d) {
return this.a + this.b + c + d;
}
const o = { a: 1, b: 3 };
// The first argument is bound to the implicit 'this' parameter; the remaining
// arguments are bound to the named parameters.
add.call(o, 5, 7); // 16
// The first argument is bound to the implicit 'this' parameter; the second
// argument is an array whose members are bound to the named parameters.
add.apply(o, [10, 20]); // 34
this и преобразование объектов
В нестрогом режиме, если функция вызывается со значением this, которое не является объектом, значение this заменяется объектом. null и undefined становятся globalThis. Примитивы, такие как 7 или 'foo', преобразуются в объекты с помощью соответствующего конструктора. Поэтому примитивное число 7 преобразуется в объект-обёртку класса Number, а строка 'foo' — в объект-обёртку класса String.
function bar() {
console.log(Object.prototype.toString.call(this));
}
bar.call(7); // [object Number]
bar.call("foo"); // [object String]
bar.call(undefined); // [object Window]
Метод bind()
Вызов f.bind(someObject) создаёт новую функцию с тем же телом и областью видимости, что и у f, но значение this навсегда привязывается к первому аргументу bind независимо от способа вызова функции.
function f() {
return this.a;
}
const g = f.bind({ a: "azerty" });
console.log(g()); // azerty
const h = g.bind({ a: "yoo" }); // bind only works once!
console.log(h()); // azerty
const o = { a: 37, f, g, h };
console.log(o.a, o.f(), o.g(), o.h()); // 37 37 azerty azerty
this в стрелочных функциях
Стрелочные функции создают замыкания над значением this окружающего контекста выполнения. В следующем примере мы создаём obj с методом getThisGetter, который возвращает функцию, возвращающую значение this. Возвращаемая функция создана как стрелочная, поэтому её this навсегда привязано к значению this окружающей функции. Значение this внутри getThisGetter можно задать при вызове, что, в свою очередь, определяет возвращаемое значение этой функции. Будем считать, что getThisGetter — нестрогая функция, то есть она содержится в нестрогом скрипте и не вложена в класс или строгую функцию.
const obj = {
getThisGetter() {
const getter = () => this;
return getter;
},
};
Мы можем вызвать getThisGetter как метод obj, привязав this к obj внутри тела метода. Возвращаемая функция присваивается переменной fn. При вызове fn возвращаемое значение this по-прежнему будет значением, заданным при вызове getThisGetter, то есть obj. Если бы возвращаемая функция не была стрелочной, при таких вызовах значение this стало бы globalThis, поскольку getThisGetter работает в нестрогом режиме.
const fn = obj.getThisGetter(); console.log(fn() === obj); // true
Однако будьте осторожны, если отвязываете метод obj, не вызывая его: getThisGetter по-прежнему является методом с изменяющимся значением this. Вызов fn2()() в следующем примере возвращает globalThis, поскольку он следует за this из fn2(), которое равно globalThis, так как функция вызвана без привязки к какому-либо объекту.
const fn2 = obj.getThisGetter; console.log(fn2()() === globalThis); // true in non-strict mode
Такое поведение очень полезно при определении функций обратного вызова. Обычно каждое функциональное выражение создаёт собственную привязку this, которая затеняет значение this из внешней области видимости. Теперь можно определять функции как стрелочные, если значение this не имеет значения, и создавать привязки this только там, где они нужны (например, в методах класса). См. пример с setTimeout().
this в геттере или сеттере
Значение this в геттерах и сеттерах зависит от объекта, у которого запрашивается свойство, а не от объекта, в котором оно определено. Функция, используемая как геттер или сеттер, привязывает this к объекту, у которого устанавливается или получается свойство.
function sum() {
return this.a + this.b + this.c;
}
const o = {
a: 1,
b: 2,
c: 3,
get average() {
return (this.a + this.b + this.c) / 3;
},
};
Object.defineProperty(o, "sum", {
get: sum,
enumerable: true,
configurable: true,
});
console.log(o.average, o.sum); // 2 6
this в обработчиках событий DOM
Если функция используется как обработчик события, её параметр this привязывается к DOM-элементу, на котором установлен слушатель (некоторые браузеры не следуют этому соглашению для слушателей, добавленных динамически с помощью методов, отличных от addEventListener()).
// 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
const elements = document.getElementsByTagName("*");
// Add bluify as a click listener so when the
// element is clicked on, it turns blue
for (const element of elements) {
element.addEventListener("click", bluify);
}
this во встроенных обработчиках событий
Если код вызывается из встроенного атрибута обработчика события, его this привязывается к DOM-элементу, на котором установлен слушатель:
<button onclick="alert(this.tagName.toLowerCase());">Show this</button>
В приведённом выше окне предупреждения отображается button. Однако обратите внимание: таким образом привязывается this только внешней области видимости:
<button onclick="alert((function () { return this; })());">
Show inner this
</button>
В этом случае параметр this внутренней функции привязывается к globalThis (то есть к объекту по умолчанию в нестрогом режиме, когда this не передаётся при вызове).
Привязанные методы в классах
Как и в случае с обычными функциями, значение this внутри методов зависит от способа их вызова. Иногда полезно переопределить это поведение, чтобы this внутри классов всегда указывало на экземпляр класса. Для этого привяжите методы класса в конструкторе:
class Car {
constructor() {
// Bind sayBye but not sayHi to show the difference
this.sayBye = this.sayBye.bind(this);
}
sayHi() {
console.log(`Hello from ${this.name}`);
}
sayBye() {
console.log(`Bye from ${this.name}`);
}
get name() {
return "Ferrari";
}
}
class Bird {
get name() {
return "Tweety";
}
}
const car = new Car();
const bird = new Bird();
// The value of 'this' in methods depends on their caller
car.sayHi(); // Hello from Ferrari
bird.sayHi = car.sayHi;
bird.sayHi(); // Hello from Tweety
// For bound methods, 'this' doesn't depend on the caller
bird.sayBye = car.sayBye;
bird.sayBye(); // Bye from Ferrari
Примечание: Классы всегда работают в строгом режиме. Вызов методов с неопределённым значением this приведёт к ошибке, если метод попытается обратиться к свойствам this.
js example-bad
const carSayHi = car.sayHi;
carSayHi(); // TypeError because the 'sayHi' method tries to access 'this.name', but 'this' is undefined in strict mode.
Однако обратите внимание: автоматически привязанные методы подвержены той же проблеме, что и использование стрелочных функций в качестве свойств класса: у каждого экземпляра класса будет собственная копия метода, что увеличивает потребление памяти. Используйте этот подход только при крайней необходимости. Можно также имитировать реализацию Intl.NumberFormat.prototype.format(): определить свойство как геттер, который при обращении возвращает привязанную функцию и сохраняет её, чтобы функция создавалась только один раз и только при необходимости.
this в инструкциях with
Хотя инструкции with устарели и недоступны в строгом режиме, они по-прежнему являются исключением из обычных правил привязки this. Если функция вызывается внутри инструкции with и эта функция является свойством объекта области видимости, значение this привязывается к объекту области видимости, как если бы существовал префикс obj..
const obj = {
foo() {
return this;
},
};
with (obj) {
console.log(foo() === obj); // true
}
Спецификации
Совместимость с браузерами
| Настольные компьютеры | Мобильные устройства | Серверы | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome для Android | Firefox для Android | Opera для Android | Safari для iOS | Samsung Internet | WebView для Android | WebView для iOS | Bun | Deno | Node.js | |
this |
1 |
12 |
1 |
9.5 |
1 |
18 |
4 |
10.1 |
1 |
1.0 |
4.4 |
1 |
1.0.0 |
1.0 |
0.10.0 |
См. также
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this