Функции в javascript. Урок 2. Ключевое слово this

Оглавление цикла уроков по функциям в javascript.

Как я уже писал в предыдущем уроке: функции в javascript — это объекты, такие же, как, скажем, массивы. Их можно присваивать переменным или полям других объектов, можно у них создавать поля и задавать любое их содержимое (someFunc.field = «value»), можно передавать в качестве параметров при вызове других функций. Да, отличие функций от других объектов — их можно вызывать, передавая какие-то параметры. Но есть также небольшое отличие от других популярных языков программирования: в javascript функции не просто вызываются, а явно или неявно применяются к неким объектам.

Формально вызов функции выглядит следующим образом:

или, что то же самое, но параметры передаются не массивом, а через запятую:


То есть у каждой функции (она ведь объект) есть методы apply и call, которые позволяют применять данную функцию к переданному в качестве первого параметра объекту (someObj). Это важно понимать, поскольку именно на этот объект ссылается ключевое слово this внутри нашей функции. «Переменная» this доступна всегда внутри функции.

Вы можете сказать «Но я просто вызываю функцию как someFunc() и не парюсь ни с какими apply и call». Да, так и есть, это называется «синтаксический сахар», вы можете вызвать функцию «по-простому», но на что тогда будет ссылаться this? На глобальный объект, то есть в случае выполнения вашего кода в браузере — на window:

С ситуацией, когда функция вызывается как метод объекта, все проще и интуитивно понятнее:

Думаю, уже понятно, почему не будет работать последний вариант: в этом случае this внутри вызываемой функции ссылается по умолчанию на window, а не на someObj. Это типичная ошибка начинающих программистов на javascript — передавать обработчику события метод объекта «как есть», обработчик же вызывает данную функцию в контексте глобального объекта, и this в вашей функции не будет ссылаться на него. Решается проблема довольно просто, нужно лишь обернуть вызов метода в функцию, в примере выше, чтоб последний вариант работал, можно сделать так:

То же самое с обработчиками событий, например, в переменной button у нас ссылка на некую кнопку на странице (хотя так вешать обработчик событий нежелательно):

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

Во время привязки мы получаем «оберточную» функцию, вызывая которую в любом контексте и передавая ей необходимые параметры, мы гарантируем, что функция будет вызвана именно в контексте нужного нам объекта, и ей будут переданы все параметры (они находятся внутри arguments у этой функции). Имея теперь в наличии функцию bind(), мы можем переписать пример с обработчиками событий таким образом:

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

Теперь привяжем метод someFunc объекта someObj к нашему новому объекту. Самый простой вариант — добавить эту функцию в наш новый объект в качестве метода:

Или можем создать обертку с нужной привязкой:

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

В следующем уроке речь пойдет о функциях-конструкторах, содержимом this в них, прототипах и отсутствии классов в javascript.

Оглавление цикла уроков по функциям в javascript.

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