Что такое this в javascript
Ключевое слово this в javascript — учимся определять контекст на практике
По просьбам некоторых читателей решил написать топик про контекст в javascript. Новички javascript часто не понимают значение ключевого слова this в javascript. Данный топик будет интересен не только новичкам, а также тем, кто просто хочет освежить данный аспект в памяти. Посмотрите пример ниже. Если вы затрудняетесь ответить на вопрос «что будет выведено в логе» хотя бы в одном из пунктов или хотите просто посмотреть ответы — добро пожаловать под кат.
1. Теория
В отличие от многих других языков программирования ключевое слово this в javascript не привязывается к объекту, а зависит от контекста вызова. Для упрощения понимания будем рассматривать примеры применительно к браузеру, где глобальным объектом является window.
1.1. Простой вызов функции
В данном случае this внутри функции f равен глобальному объекту (например, в браузере это window, в Node.js — global).
Самовызывающиеся функции (self-invoking) работают по точно такому же принципу.
1.2. В конструкторе
При вызове функции с использованием ключевого слова new функция выступает в роли конструктора, и в данном случе this указывает на создаваемый объект.
1.3. В методе объекта
Если функция запускается как свойство объекта, то в this будет ссылка на этот объект. При этом не имеет значения, откуда данная функция появилась в объекте, главное — как она вызывается, а именно какой объект стоит перед вызовом функции:
1.4. Методы apply, call
Методы apply и call позволяют задать контекст для выполняемой функции. Разница между apply и call — только в способе передачи параметров в функцию. Первый параметр обеих функций определяет контекст выполнения функции (то, чему будет равен this).
2. Разбираем задачу
Применим полученные знания к приведенной в начале топика задаче. Опять же для упрощения будем рассматривать примеры применительно к браузеру, где глобальным объектом является window.
Ключевое слово this в JavaScript. Полное* руководство
* скорее всего, я что-нибудь да упустил, но уверен, в комментариях мне это подскажут
Эту статью я пишу для своих личных нужд. Планируется, что она будет содержать в себе ответы на все вопросы, которые мне задают студенты на эту тему. Если она пригодится кому-то ещё — здорово.
Введение
Ключевое слово this — одна из наиболее запутывающих особенностей языка JavaScript. Пришедшее из Java, оно было призвано помочь в реализации ООП. Я какое-то время писал на Java, и должен сказать, что за это время у меня, может быть, один раз возникло сомнение, чему равняется this в конкретном месте кода. В JavaScript такие сомнения могут возникать каждый день — по крайней мере, до того момента, как выучишь несколько простых, но неочевидных правил.
Заблуждения о this
Существует несколько распространённых заблуждений относительно этого ключевого слова. Я хочу их быстренько развеять перед тем, как перейти к сути.
this — это лексический контекст.
В общем случае это неправда. Это легко проверить.
this — это объект, которому принадлежит метод
Опять же, это правда во многих конкретных случаях, но не всегда. Важно то, каким способом вызывается функция, а не то, является ли она свойством какого-то объекта. Это понятно даже из очень простой логики: предположим, одна и та же функция является свойством одновременно двух объектов.
Так какой же из этих объектов будет её this’ом?
this — это джедайская техника, которую, изучив, нужно использовать везде
Как определить значение this
Здесь я постараюсь дать строгий и лаконичный алгоритм, с помощью которого даже неискушённый кодер сумеет понять, чему равняется this в его конкретном случае. Более многословные пояснения буду спрятаны под спойлеры, дабы не захламлять визуальное пространство.
У не стрелочной и не связанной (bound) функции значение this зависит от обстоятельств, в которых она была вызвана. Если вы не вызываете её лично, а передаёте куда-то, то в качестве this может быть или не быть подставлено неизвестное вам значение.
Собственно, из этого механизма (а также — из опыта работы с другими языками) растут ноги у убеждения, что » this — это объект, чей метод мы вызвали». Пожалуй, я просто напишу код.
Или, как я уже говорил в секции «заблуждения», многие считают, что если функция является методом объекта, созданного с помощью классов ES6, то уж в ней-то this всегда будет равен этому объекту. Это тоже неправда.
Так вот, если мы дошли до этого пункта, значит, прочие обстоятельства вызова нашей функции не имеют значения. И всё сводится к тому, находимся мы в строгом режиме или нет.
В ES6 модулях строгий режим включен по умолчанию.
Ключевое слово this в JavaScript для начинающих
Что такое this?
Причина, по которой this вызывает столько путаницы у новичков, заключается в том, что контекст this меняется в зависимости от его использования.
Ситуации, когда this указывает на объект window
Если вы попытаетесь обратиться к ключевому слову this в глобальной области видимости, оно будет привязано к глобальному контексту, то есть — к объекту window в браузере.
Попробуйте выполнить этот код, например, в консоли браузера:
Использование this внутри объекта
This и вложенные объекты
Применение this во вложенных объектах может создать некоторую путаницу. В подобных ситуациях стоит помнить о том, что ключевое слово this относиться к тому объекту, в методе которого оно используется. Рассмотрим пример.
Особенности стрелочных функций
Стрелочные функции ведут себя не так, как обычные функции. Вспомните: при обращении к this в методе объекта, этому ключевому слову соответствует объект, которому принадлежит метод. Однако это не относится к стрелочным функциям. Вместо этого, this в таких функциях относится к глобальному контексту (к объекту window ). Рассмотрим следующий код, который можно запустить в консоли браузера.
Прислушаемся к MDN и не будем использовать стрелочные функции в качестве методов объектов.
Использование this в обычных функциях
Обращение к this из функции, которая была объявлена за пределами объекта, а потом назначена в качестве его метода
Ключевое слово new и this
Вот как можно работать со стандартными конструкторами JavaScript.
Вот ещё один пример использования функций-конструкторов.
О важности ключевого слова new
При вызове функции-конструктора с использованием ключевого слова new ключевое слово this указывает на новый объект, который, после некоторой работы над ним, будет возвращён из этой функции. Ключевое слово this в данной ситуации весьма важно. Почему? Всё дело в том, что с его помощью можно, используя единственную функцию-конструктор, создавать множество однотипных объектов.
Итоги
Уважаемые читатели! Возникали ли у вас сложности с пониманием ключевого слова this в JavaScript?
Что такое this в javascript
Поведение ключевого слова this в JavaScript несколько отличается по сравнению с остальными языками. Имеются также различия при использовании this в строгом и нестрогом режиме.
Исходный код этого интерактивного примера хранится в репозитории на GitHub. Если вы хотите поучаствовать в создании этого интерактивного примера, склонируйте репозиторий про адресу https://github.com/mdn/interactive-examples и присылайте пулреквест.
Синтаксис
Значение
Свойство контекста выполнения кода (global, function или eval), которое в нестрогом режиме всегда является ссылкой на объект, а в строгом режиме может иметь любое значение.
Global контекст
В глобальном контексте выполнения (за пределами каких-либо функций) this ссылается на глобальный объект вне зависимости от режима (строгий или нестрогий).
Function контекст
В пределах функции значение this зависит от того, каким образом вызвана функция.
Простой вызов
Пример 1
Пример 2
Метод bind
Стрелочные функции
Note: если аргумент this передаётся в call, bind или apply при вызове стрелочной функции, он будет проигнорирован. Вы всё ещё можете добавить аргументы к вызову, но первый аргумент (thisArg) должен быть установлен в null.
Несмотря ни на что, this стрелочной функции foo() имеет то же значение, что и при создании функции (глобальный объект в примере выше). То же самое касается стрелочных функций, созданных внутри других функций: их this будет привязан к окружению.
В методе объекта
Когда функция вызывается как метод объекта, используемое в этой функции ключевое слово this принимает значение объекта, по отношению к которому вызван метод.
this в цепочке object’s prototype
Это же представление справедливо и для методов, определённых где-либо в цепочке object’s prototype. Если метод находится в цепочке прототипов, то this ссылается на объект, на котором был вызван метод, т.е. так, словно метод является методом самого объекта, а не прототипа.
this с геттерами/сеттерами
Все те же утверждения справедливы, если функция вызывается из геттера или сеттера. Для функции, которая используется как геттер или сеттер this привязан к объекту, свойство которого необходимо извлечь через геттер/сеттер.
В конструкторе
Когда функция используется как конструктор (с ключевым словом new ), this связано с создаваемым новым объектом.
call и apply
Как обработчик событий DOM
Когда функция используется как обработчик событий, this присваивается элементу с которого начинается событие (некоторые браузеры не следуют этому соглашению для обработчиков, добавленных динамически с помощью всех методов, кроме addEventListener ).
В инлайновом обработчике событий
Когда код вызван из инлайнового обработчика, this указывает на DOM-элемент, в котором расположен код события:
Код выше выведет ‘ button ‘. Следует отметить, что this будет указывать на DOM-элемент только во внешних (не вложенных) функциях:
В этом случае this вложенной функции не будет установлен, так что будет возвращён global/window объект.
Форум
Discord чат
Описание, примеры
Текущий объект не является жестко фиксированным и зависит от контекста вызова функции. Он является, своего рода, скрытым параметром.
Есть четыре различных варианта его передачи.
Тип | Способ | this |
неявно, через вызов метода | object.method(. ) | object |
явно, через call | function.call(object. ) | object |
явно, через apply | function.apply(object. ) | object |
неявно, через вызов new | new constructor(. ) | новый, создаваемый объект |
Если ни один из этих способов не задействован, то this указывает на глобальный объект: в браузере это window.
При манипуляциях с DOM при помощи javascript, this обычно используется для работы с событиями. При этом значение this указывает на текущий DOM-элемент, в контексте которого вызван обработчик.
Привязка методов
Так как this не привязано жестко к объекту, то можно привязывать один и тот же метод к любым классам.
См. также
Здравствуйте, А как быть с многоуровневыми объектами?
Точнее: как получить доступ к старшему объекту?
Если ничего не путаю, необходимо будет обращаться напрямую. чтобы получить subO в f, необходимо обращаться как o.subO, и так далее.
Помогите, пожалуйста. Весь вечер голову ломаю.
function Round(px, py, pR) <
this.x=px;
this.y=py;
this.R=pR;
this.getLength=mGetLength();
>
function mGetLength() <
return this.x;
>
var d=new Round(1, 2, 3);
var f=d.getLength;
Почему возвращает undefined?
если написАть var f=d.x; или var f=d.y; то их возвращает, а вот метод getLength не реализуется почему то
мне кажется, что ошибка здесь:
«function mGetLength() <
return this.x;
>»
думаю, в данном случае не «Round» выступает в качестве объекта, а «mGetLength».. а у mGetLength параметра «х» нету, поэтому и «undefined».
И вообще странная функция какая-то.. у тебя же уже есть параметр «х», для чего длину добавлять отдельно, да еще и функцией? О_о или я не правильно понял что?
Если кому-то еще интересно, то ошибки две:
this.getLength=mGetLength;
скобки не нужны, если мы хотим, чтоб getLength была не переменной, а методом.
А вот при вызове метода наоборот нужны скобки:
var f=d.getLength();
Там return this.x для примера только, там мат. действие в оригинале должно быть, умножение this.x, this.y и this.pR, к примеру, это я пока для примера поставил, пока разбирался)
«думаю, в данном случае не «Round» выступает в качестве объекта, а «mGetLength».. а у mGetLength параметра «х» нету, поэтому и «undefined».»
Я тоже так думал, кстати, но у меня книга есть, оттуда пример, там так написАно 0_о
А как сделать, чтоб mGetLength обращался за переменной в Round?
Только не сильно меняя код, я именно с назначением методов пытаюсь разобраться
Попробуй перед функцией this.getLength=mGetLength();
поставить строку that = this;
и внутри функции mGetLength() использовать that вместо this.
Доброго времени суток, созрел вопрос. Вот почему this может затеряться при, например, присваивании функции, в которой он прописан, какому-либо другому выражению или переменной? Например: