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

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

Немного об этом

Если вы когда-либо изучали или общались с друзьями-программистами о JavaScript, вы, вероятно, слышали, как они говорят что-то вроде: «О да, в JS ВСЁ является объектом!» Хотя тема этого конкретного поста выходит за рамки этого разговора, они, тем не менее, в значительной степени верны: объекты — один из самых важных и основных строительных блоков JS; действительно объекты в JS есть ВЕЗДЕ!

Итак, что такое this? Ну, this — это специальный референт объекта JS. Даже если это не типизировано напрямую, this работает все время, пока выполняется код JS.

Как следует из названия, JS — это язык сценариев, что означает отсутствие этапа компиляции при выполнении кода JS. Вместо этого интерпретатор JS начинает с начала скрипта и выполняет строку за строкой. Среда выполнения JS создает «стек» этих фрагментов кода в очереди для выполнения, и любой код, находящийся на «верху» стека, является следующим в очереди; этот фрагмент кода «вверху» также является контекстом, на который ссылается this.

Три «это»

Имея это в виду, this всегда относится к одному из трех элементов: глобальному объекту и экземпляру класса, созданного с помощью ключевого слова new, или родительскому объекту выполняемого метода.

Глобальное «это»

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

function sayHi () { 
  console.log(‘a’, ‘How are ya now?’); 
  console.log(‘b’, ‘Good n’you?’); 
  console.log(‘a’, ‘Not so bad.’); 
  console.log(‘1’, this === window); 
} 
sayHi(); // logs above a,b greeting, as well as '1' logs ‘true,’ as the current context is the Global Object.

Ключевое слово «новое»

Когда кто-то создает экземпляр класса с помощью ключевого слова new, this будет ссылаться на этот экземпляр, например:

function Sandwich(type, size) { 
  this.type = type; 
  this.size = size; 
  this.eat = function() { 
    console.log(`This ${this.type}, ${this.size} sandwich is awesome!`); 
  }
} 
let sammy1 = new Sandwich(“tasty”, “large”);
sammy1.eat(); // logs: ‘This tasty, large sandwich is awesome!’
let sammy2 = new Sandwich(“delish”, “gigantic”);
sammy2.eat(); // logs: ‘This delish, gigantic sandwich is awesome!’

Родитель/владелец вызываемого метода

Наконец, референт this может ссылаться на родителя/владельца исполняемого метода, например:

function greeting () { 
  console.log(‘1’, ‘hi’); 
  console.log(‘2’, this === window); 
} 
let friend = { 
  highFive: true, 
  greeting: greeting
} 
greeting(); // ‘1’ will log ‘hi’, and ‘2’ will log ‘true’ as this is being invoked in the Global context;
friend.greeting(); // ‘1’ will log ‘hi’, and ‘2’ will log ‘false’ as this is being invoked by and in the friend object;

Подводя итог, хотя this может немного сбивать с толку, а иногда и вводить в заблуждение, невероятно важно понимать, в каком контексте ваши this es имеют в виду. Помните, что this всегда относится к одному из трех элементов: глобальному объекту и экземпляру класса, созданного с помощью ключевого слова new, или родительскому объекту выполняемого метода.

Несколько дружеских советов напоследок: понимание того, на что «указывает» this, сделает ваш код менее глючным, ваших боссов — счастливее, а вашу жизнь — проще!