Что такое this в javascript
Перейти к содержимому

Что такое this в javascript

  • автор:

Как работает this, bind, call и apply в JavaScript

Ключевое слово this – очень важное понятие в JavaScript, но в работе с ним особенно легко запутаться как новичкам, так и опытным разработчикам, много работавшим с другими языками программирования. В JavaScript this – это ссылка на объект. Объект, на который ссылается это ключевое слово, может неявно варьироваться в зависимости от того, является ли он глобальным. Также он может явно варьироваться в зависимости от использования методов-прототипов Function: bind, call и apply.

Это немного сложная тема, но она пригодится вам в разработке ваших первых программ на JavaScript. Если вы пытаетесь получить доступ к элементу или событию в объектной модели документа (DOM), создаете классы для записи в стиле объектно-ориентированного программирования или используете свойства и методы обычных объектов, вы столкнетесь с ключевым словом this.

В этом мануале вы узнаете, как по контексту определить, на что неявно ссылается this, и как использовать методы bind, call и apply для явного определения значения this.

Неявный контекст

Существует четыре основных контекста, в которых можно неявно определить значение ключевого слова this:

  • глобальный контекст
  • как метод внутри объекта
  • как конструктор в функции или классе
  • как обработчик событий DOM

Глобальный контекст

В глобальном контексте this ссылается на глобальный объект. Когда вы работаете в браузере, глобальный контекст – это окно. Когда вы работаете в Node.js, глобальный контекст – это global.

Примечание: Если вы еще не знакомы с понятием области видимости в JavaScript, ознакомьтесь с нашим мануалом Переменные, области и поднятие переменных в JavaScript.

В качестве примеров мы будем использовать код в консоли браузера Developer Tools.

Если вы зарегистрируете значение this без какого-либо другого кода, вы увидите, к какому объекту относится this.

console.log(this)
Window

Вы увидите, что this – это окно, которое является глобальным объектом браузера.

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

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

function printThis() <
console.log(this)
>
printThis()
Window

Даже внутри функции this все равно относится к window, или к глобальному объекту.

Однако при использовании строгого режима контекст this внутри функции в глобальном контексте будет undefined.

‘use strict’
function printThis() <
console.log(this)
>
printThis()
undefined

Как правило, строгий режим использовать безопаснее, так как он позволяет уменьшить вероятность непредвиденной области применения ключевого слова this. Вряд ли кто-то захочет обратиться к объекту window, используя this.

За дополнительной информацией о строгом режиме и о том, какие изменения он вносит в отношении ошибок и безопасности, обращайтесь к документации на MDN.

Метод объекта

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

const america = <
name: ‘The United States of America’,
yearFounded: 1776,
describe() <
console.log(`$<this.name> was founded in $<this.yearFounded>.`)
>,
>
america.describe()
«The United States of America was founded in 1776.»

В этом примере this – america.

Во вложенном объекте this ссылается на текущую область метода. В следующем примере this.symbol в объекте details ссылается на details.symbol.

const america = <
name: ‘The United States of America’,
yearFounded: 1776,
details: <
symbol: ‘eagle’,
currency: ‘USD’,
printDetails() <
console.log(`The symbol is the $<this.symbol> and the currency is $<this.currency>.`)
>,
>,
>
america.details.printDetails()
«The symbol is the eagle and the currency is USD.»

Проще говоря, this ссылается на объект с левой стороны от точки при вызове метода.

Конструктор функций

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

function Country(name, yearFounded) <
this.name = name
this.yearFounded = yearFounded
this.describe = function() <
console.log(`$<this.name> was founded in $<this.yearFounded>.`)
>
>
const america = new Country(‘The United States of America’, 1776)
america.describe()
«The United States of America was founded in 1776.»

В этом контексте this ссылается на экземпляр Country, который содержится в константе america.

Конструктор класса

Конструктор в классе действует так же, как в функции.

class Country <
constructor(name, yearFounded) <
this.name = name
this.yearFounded = yearFounded
>
describe() <
console.log(`$<this.name> was founded in $<this.yearFounded>.`)
>
>
const america = new Country(‘The United States of America’, 1776)
america.describe()

Ключевое слово this в методе describe относится к экземпляру Country, которым является america.

«The United States of America was founded in 1776.»

Обработчик событий DOM

В браузере есть специальный контекст this для обработчиков событий. В обработчике событий, вызываемом addEventListener ключевое слово this будет ссылаться на event.currentTarget. Чаще всего по мере необходимости разработчики просто используют event.target или event.currentTarget для доступа к элементам в DOM, но так как ссылка this изменяется в этом контексте, это важно знать.

В следующем примере мы создадим кнопку, добавим к ней текст и поместим ее в DOM. Когда мы записываем значение this в обработчик события, он выводит цель.

const button = document.createElement(‘button’)
button.textContent = ‘Click me’
document.body.append(button)
button.addEventListener(‘click’, function(event) <
console.log(this)
>)
<button>Click me</button>

Как только вы вставите этот код в свой браузер, на странице появится кнопка с надписью «Click me». Если вы нажмете кнопку, вы увидите <button>Click me</button> в консоли, так как нажатие кнопки регистрирует элемент, который является самой кнопкой. Как видите, this ссылается на целевой элемент, который является элементом, к которому мы добавили прослушиватель событий.

Явный контекст

Во всех предыдущих примерах значение this определялось его контекстом –глобальным, в объекте, в функции или классе или в обработчике событий DOM. Но используя call, apply или bind, вы можете явно определить, на что ссылается this.

Трудно точно определить, когда нужно использовать call, apply или bind, так как это зависит от контекста вашей программы. Метод bind может быть особенно полезен, если вы хотите использовать события для доступа к свойствам одного класса в другом классе. Например, если вы хотите написать простую игру, вы можете разделить пользовательский интерфейс и ввод-вывод на один класс, а игровую логику и состояние – на другой. Так как игровая логика должна иметь доступ к вводу, например нажатию клавиши и кликам, вам нужно связать (bind) события, чтобы получить доступ к значению this класса игровой логики.

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

Методы call и apply

call и apply очень похожи – они вызывают функцию с указанным контекстом this и дополнительными аргументами. Единственная разница между call и apply заключается в том, что call требует, чтобы аргументы передавались по одному, а apply принимает их в виде массива.

В этом примере мы создадим объект и функцию, которая ссылается на this, но не имеет контекста this.

const book = <
title: ‘Brave New World’,
author: ‘Aldous Huxley’,
>
function summary() <
console.log(`$<this.title> was written by $<this.author>.`)
>
summary()
«undefined was written by undefined»

Поскольку summary и book не связаны, сам по себе вызов summary будет выводить только неопределенное значение undefined, так как он ищет эти свойства в глобальном объекте.

Примечание: Попытка сделать это в строгом режиме приведет к Uncaught TypeError: Cannot read property ‘title’ of undefined, так как само ключевое слово this будет undefined.

Тем не менее, вы можете использовать call и apply для вызова контекста this для book в функции.

summary.call(book)
// or:
summary.apply(book)
«Brave New World was written by Aldous Huxley.»

Теперь между book и summary существует связь. Давайте точно узнаем, на что ссылается this.

function printThis() <
console.log(this)
>
printThis.call(book)
// or:
whatIsThis.apply(book)

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

Как мы уже говорили, call и apply почти одинаковы, но есть одно небольшое отличие. Помимо возможности передавать контекст this в качестве первого аргумента, вы также можете передавать apply дополнительные аргументы.

function longerSummary(genre, year) <
console.log(
`$<this.title> was written by $<this.author>. It is a $ novel written in $.`
)
>

При использовании call каждое дополнительное значение, которое вы хотите передать, отправляется в качестве дополнительного аргумента.

longerSummary.call(book, ‘dystopian’, 1932)
«Brave New World was written by Aldous Huxley. It is a dystopian novel written in 1932.»

Если вы попытаетесь отправить те же аргументы с помощью apply, произойдет вот что:

longerSummary.apply(book, ‘dystopian’, 1932)
Uncaught TypeError: CreateListFromArrayLike called on non-object at <anonymous>:1:15

При использовании apply вы должны передать все аргументы в массиве.

longerSummary.apply(book, [‘dystopian’, 1932])
«Brave New World was written by Aldous Huxley. It is a dystopian novel written in 1932.»

Разница между передачей аргументов по отдельности или в массиве невелика, но об этом важно знать. Использовать метод apply иногда может быть проще и удобнее, так как он не требует изменения вызова функции, если некоторые детали параметров изменились.

Метод bind

И call, и apply являются одноразовыми методами – если вы вызываете метод с контекстом this, он примет его, но исходная функция останется неизменной.

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

const braveNewWorldSummary = summary.bind(book)
braveNewWorldSummary()
«Brave New World was written by Aldous Huxley»

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

const braveNewWorldSummary = summary.bind(book)
braveNewWorldSummary() // Brave New World was written by Aldous Huxley.
const book2 = <
title: ‘1984’,
author: ‘George Orwell’,
>
braveNewWorldSummary.bind(book2)
braveNewWorldSummary() // Brave New World was written by Aldous Huxley.

Хотя этот пример пытается связать braveNewWorldSummary еще раз, он сохраняет оригинальный контекст this.

Стрелочные функции

Стрелочные функции не имеют привязки this. Вместо этого они переходят на следующий уровень исполнения.

const whoAmI = <
name: ‘Leslie Knope’,
regularFunction: function() <
console.log(this.name)
>,
arrowFunction: () => <
console.log(this.name)
>,
>
whoAmI.regularFunction() // «Leslie Knope»
whoAmI.arrowFunction() // undefined

Стрелочные функции полезно использовать в тех случаях, когда ключевое слово this должно ссылаться на внешний контекст. Например, если внутри класса у вас есть прослушиватель событий, вы, вероятно, захотите, чтобы this ссылалось на какое-то значение в классе.

В этом примере мы создадим и добавим кнопку в DOM, как мы делали раньше, но у класса будет прослушиватель событий, который будет изменять текстовое значение кнопки при нажатии.

const button = document.createElement(‘button’)
button.textContent = ‘Click me’
document.body.append(button)
class Display <
constructor() <
this.buttonText = ‘New text’
button.addEventListener(‘click’, event => <
event.target.textContent = this.buttonText
>)
>
>
new Display()

Если вы нажмете кнопку, текстовое содержимое изменится на значение buttonText. Если бы вы не использовали здесь стрелочную функцию, this было бы равно event.currentTarget, и вы не смогли бы использовать его для доступа к значению в классе без явного его связывания. Эта тактика часто используется в методах классов в таких средах, как React.

Заключение

В этой статье вы узнали о ключевом слове this в JavaScript и о множестве различных значений, которые оно могло бы иметь в неявном контексте и при явном связывании посредством методов bind, call и apply. Также вы знаете, как отсутствие привязки this в стрелочных функциях можно использовать для ссылки на другой контекст. Обладая этими знаниями, вы сможете определить значение this в своих программах.

Что такое this в javascript

Поведение ключевого слова this в JavaScript несколько отличается по сравнению с остальными языками. Имеются также различия при использовании this в строгом и нестрогом режиме.

В большинстве случаев значение this определяется тем, каким образом вызвана функция. Значение this не может быть установлено путём присваивания во время исполнения кода и может иметь разное значение при каждом вызове функции. В ES5 представлен метод bind() , который используется для привязки значения ключевого слова this независимо от того, как вызвана функция . Также в ES2015 представлены стрелочные функции , которые не создают собственные привязки к this (они сохраняют значение this лексического окружения, в котором были созданы).

Интерактивный пример

Синтаксис

Значение

Свойство контекста выполнения кода (global, function или eval), которое в нестрогом режиме всегда является ссылкой на объект, а в строгом режиме может иметь любое значение.

Global контекст

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

Примечание: вы всегда можете легко получить объект global, используя глобальное свойство globalThis , независимо от текущего контекста, в котором выполняется ваш код.

Function контекст

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

Простой вызов

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

В строгом режиме, если значение this не установлено в контексте выполнения, оно остаётся undefined , как показано в следующем примере:

Примечание: Во втором примере this должно иметь значение undefined , потому что функция f2 была вызвана напрямую, а не как метод или свойство объекта (например, window.f2() ). Реализация этой особенности не поддерживалась в некоторых браузерах, когда они впервые начали поддерживать строгий режим . В результате они некорректно возвращали объект window .

Для того, чтобы при вызове функции установить this в определённое значение, используйте call() или apply() , как в следующих примерах.

Пример 1

Пример 2

Обратите внимание, что в нестрогом режиме, если значение, переданное в call или apply как this , не является объектом, будет сделана попытка преобразовать его в объект с помощью внутренней операции ToObject . Таким образом, если переданное значение является примитивом, таким как 7 или ‘foo’ , оно будет преобразовано в Object с использованием связанного конструктора, так что примитивное число 7 будет преобразовано в объект так, как будто с помощью new Number(7) , а строка ‘foo’ — как будто с помощью new String(‘foo’) , например

Метод bind

ECMAScript 5 представил Function.prototype.bind() . Вызов f.bind(someObject) создаёт новую функцию с тем же телом и областью действия, что и f , но там, где в исходной функции используется this , в новой функции оно постоянно будет связано с первым аргументом bind , независимо от того, как функция используется.

Стрелочные функции

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

Примечание: Note: если аргумент this передаётся в call, bind или apply при вызове стрелочной функции, он будет проигнорирован. Вы всё ещё можете добавить аргументы к вызову, но первый аргумент (thisArg) должен быть установлен в null.

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

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

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

В методе объекта

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

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

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

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

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

this в цепочке object’s prototype

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

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

this с геттерами/сеттерами

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

В конструкторе

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

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

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

call и apply

Когда в теле функции используется ключевое слово this , его значение может быть привязано к конкретному объекту в вызове при помощи методов call или apply , которые наследуются всеми функциями от Function.prototype .

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

Как обработчик событий DOM

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

В инлайновом обработчике событий

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

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

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

Object methods, "this"

Objects are usually created to represent entities of the real world, like users, orders and so on:

And, in the real world, a user can act: select something from the shopping cart, login, logout etc.

Actions are represented in JavaScript by functions in properties.

Method examples

For a start, let’s teach the user to say hello:

Here we’ve just used a Function Expression to create a function and assign it to the property user.sayHi of the object.

Then we can call it as user.sayHi() . The user can now speak!

A function that is a property of an object is called its method.

So, here we’ve got a method sayHi of the object user .

Of course, we could use a pre-declared function as a method, like this:

When we write our code using objects to represent entities, that’s called object-oriented programming, in short: “OOP”.

OOP is a big thing, an interesting science of its own. How to choose the right entities? How to organize the interaction between them? That’s architecture, and there are great books on that topic, like “Design Patterns: Elements of Reusable Object-Oriented Software” by E. Gamma, R. Helm, R. Johnson, J. Vissides or “Object-Oriented Analysis and Design with Applications” by G. Booch, and more.

Method shorthand

There exists a shorter syntax for methods in an object literal:

As demonstrated, we can omit "function" and just write sayHi() .

To tell the truth, the notations are not fully identical. There are subtle differences related to object inheritance (to be covered later), but for now they do not matter. In almost all cases, the shorter syntax is preferred.

“this” in methods

It’s common that an object method needs to access the information stored in the object to do its job.

For instance, the code inside user.sayHi() may need the name of the user .

To access the object, a method can use the this keyword.

The value of this is the object “before dot”, the one used to call the method.

Here during the execution of user.sayHi() , the value of this will be user .

Technically, it’s also possible to access the object without this , by referencing it via the outer variable:

…But such code is unreliable. If we decide to copy user to another variable, e.g. admin = user and overwrite user with something else, then it will access the wrong object.

That’s demonstrated below:

If we used this.name instead of user.name inside the alert , then the code would work.

“this” is not bound

In JavaScript, keyword this behaves unlike most other programming languages. It can be used in any function, even if it’s not a method of an object.

There’s no syntax error in the following example:

The value of this is evaluated during the run-time, depending on the context.

For instance, here the same function is assigned to two different objects and has different “this” in the calls:

The rule is simple: if obj.f() is called, then this is obj during the call of f . So it’s either user or admin in the example above.

We can even call the function without an object at all:

In this case this is undefined in strict mode. If we try to access this.name , there will be an error.

In non-strict mode the value of this in such case will be the global object ( window in a browser, we’ll get to it later in the chapter Global object). This is a historical behavior that "use strict" fixes.

Usually such call is a programming error. If there’s this inside a function, it expects to be called in an object context.

If you come from another programming language, then you are probably used to the idea of a "bound this ", where methods defined in an object always have this referencing that object.

In JavaScript this is “free”, its value is evaluated at call-time and does not depend on where the method was declared, but rather on what object is “before the dot”.

The concept of run-time evaluated this has both pluses and minuses. On the one hand, a function can be reused for different objects. On the other hand, the greater flexibility creates more possibilities for mistakes.

Here our position is not to judge whether this language design decision is good or bad. We’ll understand how to work with it, how to get benefits and avoid problems.

Arrow functions have no “this”

Arrow functions are special: they don’t have their “own” this . If we reference this from such a function, it’s taken from the outer “normal” function.

For instance, here arrow() uses this from the outer user.sayHi() method:

That’s a special feature of arrow functions, it’s useful when we actually do not want to have a separate this , but rather to take it from the outer context. Later in the chapter Arrow functions revisited we’ll go more deeply into arrow functions.

Summary

  • Functions that are stored in object properties are called “methods”.
  • Methods allow objects to “act” like object.doSomething() .
  • Methods can reference the object as this .

The value of this is defined at run-time.

  • When a function is declared, it may use this , but that this has no value until the function is called.
  • A function can be copied between objects.
  • When a function is called in the “method” syntax: object.method() , the value of this during the call is object .

Please note that arrow functions are special: they have no this . When this is accessed inside an arrow function, it is taken from outside.

Tasks

Using "this" in object literal

Here the function makeUser returns an object.

What is the result of accessing its ref ? Why?

Answer: an error.

That’s because rules that set this do not look at object definition. Only the moment of call matters.

Here the value of this inside makeUser() is undefined , because it is called as a function, not as a method with “dot” syntax.

The value of this is one for the whole function, code blocks and object literals do not affect it.

So ref: this actually takes current this of the function.

We can rewrite the function and return the same this with undefined value:

What Does 'this' Mean in JavaScript? The this Keyword Explained with Examples

Kingsley Ubah

Kingsley Ubah

What Does 'this' Mean in JavaScript? The this Keyword Explained with Examples

To understand what this truly means in JavaScript, let’s take a look at a very similar concept in the English Language: Polysemy.

Let’s consider the word «run«. Run is a single word which could mean many different things depending on the context.

  • “I will run home” – means to move quickly on foot
  • “She ran the 1500m” – means to run in a race
  • “He is running for president” – means vying for an official position
  • “The app is running” – means the software application is still open and active
  • “Go for a run” – means running as a form of exercise

and the list goes on.

A similar scenario plays out when you use the this keyword in your JavaScript code. When you do so, it automatically resolves to an object or scope depending on the context at which is was defined.

What are the possible contexts? And how can we use that information to deduce which object a this call will resolve to?

this Context

When used in a function, the this keyword simply points to an object to which it is bound. It answers the question of where it should get some value or data from:

A function with a «this» reference

In the function above, the this keyword is referring to an object to which it is bound so it gets the «name» property from there.

But how do you know which object the function is bound to? How do you find out what this is referring to?

To do so, we need to take a detailed look at how functions are bound to objects.

Types of Binding in JavaScript

There are generally four kinds of bindings:

  • Default Binding
  • Implicit Binding
  • Explicit Binding
  • Constructor Call Binding

Default Binding in JavaScript

One of the first rules to remember is that if the function housing a this reference is a standalone function, then that function is bound to the global object.

As you can see, name() is a standalone, unattached function, so it is bound to the global scope. As a result, the this.name reference resolves to the global variable const name = ‘Kingsley’ .

This rule, however, doesn’t hold if name() were to be defined in strict mode:

undefined in strict mode

When set in strict mode, the this reference is set to undefined.

Implicit Binding in JavaScript

Another scenario to look out for is whether the function is attached to an object (its context) at the call site.

According to the binding rule in JavaScript, a function can use an object as its context only if that object is bound to it at the call site. This form of binding is known as implicit binding.

Here is what I mean by that:

Put simply, when you call a function using dot notation, this is implicitly bound to the object the function is being called from.

In this example, since alert is being called from myObj , the this keyword is bound to myObj . So when alert is called with myObj.alert() , this.age is 22, which is the age property of myObj .

Let’s look at another example:

Here, because alert is ultimately being called from nestedObj , this is implicitly bound to nestedObj instead of myObj .

An easy way to figure out which object this is implicitly bound to is to look at which object is to the left of the dot ( . ):

Explicit binding in JavaScript

We saw that implicit binding had to do with having a reference in that object.

But what if we want to force a function to use an object as its context without putting a property function reference on the object?

We have two utility methods to achieve this: call() and apply() .

Along with a couple other set of utility functions, these two utilities are available to all functions in JavaScript via the [[Prototype]] mechanism.

To explicitly bind a function call to a context, you simply have to invoke the call() on that function and pass in the context object as parameter:

Now here’s the fun part. Even if you were to pass around that function multiple times to new variables (currying), every invocation will use the same context because it has been locked (explicitly bound) to that object. This is called hard binding.

Hard binding is a perfect way to lock a context into a function call and truly make that function into a method.

Constructor Call Binding in JavaScript

The final and perhaps most interesting kind of binding is the new binding which also accentuates the unusual behavior of JavaScript in comparison to other class-based languages.

When a function is invoked with the new keyword in front of it, otherwise known as a constructor call, the following things occur:

  1. A brand new object is created (or constructed)
  2. The newly constructed object is [[Prototype]]-linked to the function that constructed it
  3. The newly constructed object is set as the this binding for that function call.

Let’s see this in code to get a better understanding:

By calling giveAge(. ) with new in front of it, we’ve constructed a new object and set that new object as the this for the call of foo(. ) . So new is the final way that you can bind a function call’s this .

Wrapping Up

  • The this keyword, when used in a function, binds that function to a context object
  • There are four kinds of bindings: default binding, implicit binding, explicit binding and constructor call binding (new)
  • Knowing these four rules will help you easily discern the context for a this reference.

An Image Explaining the

An Image Explaining the ‘this’ keyword

If you liked or benefited from this article and would like to support me, you can buy me a coffee here.

You can also reach me on Twitter. Be sure to check out my blog for more JavaScript and programming related content.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *