Для программистов, плохо знакомых с 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
, сделает ваш код менее глючным, ваших боссов — счастливее, а вашу жизнь — проще!