Ключевое слово this и контекст в JavaScript

Содержание

Daria Sidorova

Овладение концепцией использования this и умение применять его со знанием дела не представляют особых трудностей.

Основы this

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

Запомните: Контекст имеет смысл только внутри функций.

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

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

Отслеживание объекта caller

Рассмотрим изменения ключевого слова this в зависимости от контекста:

Классы и экземпляры классов

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

Ошибка: вложенные вызовы функции

Иногда мы оказываемся не в том контексте, которого мы ожидали. Это может произойти при вызове функции внутри контекста другого объекта. Самый распространенный пример при использовании setTimeout или setInterval :

React

При работе с React подобные ситуации скоро останутся в прошлом, благодаря Hooks. Но на данный момент все еще необходимо связать ( bind ) все функции тем или иным способом (подробнее об этом позже).

Рассмотрим два простых компонента класса React:

Чтобы решить эту проблему, необходимо связать ( bind ) методы в классах при передаче их из компонента, в котором они определены.

Рассмотрим еще один базовый пример:

Решение — bind

Лучшее решение в этой ситуации — связать ( bind ) методы, которые будут переданы из первоначального объекта или класса. Есть несколько способов связывания функций, но самый распространенный (даже в React) — это связать их в конструкторе. Нужно добавить эту строку в конструктор Battle :

Стрелочные функции `() => <>` автоматически привязывают функцию к контексту объявления.

Функции apply и call

Они обе выполняют одно и то же действие, различается лишь их синтаксис. В обоих случаях контекст передается в качестве первого аргумента. apply охватывает массив других аргументов, а при использовании call можно просто разделить другие аргументы запятыми. И что же они выполняют? Оба метода устанавливают контекст для одного определенного вызова функции. При вызове функции без метода call контекст устанавливается по умолчанию (или даже связанный контекст). Пример:

Вот и все. Надеюсь, вы разобрались в том, как использовать this в JavaScript.

Ошибка определение функции не поддерживается в этом контексте создайте функции в файле кода

Цитатник веб-разработчиков В тексте курса вы встретите цитаты, высказанные в разное время разработчиками системы и разработчиками проектов на базе Bitrix Framework. Надеемся, что такие неформальные замечания внесут некоторое разнообразие в процесс изучения. Заодно опытные специалисты поделятся и своим опытом.

Чтобы научиться программировать в Bitrix Framework, нет необходимости изучать всю линейку курсов. Но есть моменты, которые необходимо знать разработчикам о системе, они раскрыты в начальных курсах:

Как построен курс

Общепринятая градация квалификации разработчиков в рамках курса обозначает что:

Начальные требования к подготовке

Для успешного изучения курса и овладения мастерством разработки сайтов на Bitrix Framework необходимо владеть (хотя бы на начальном уровне):

Тесты

После изучения курса вам будет предложено пройти тесты на сертификацию. При успешной сдаче последовательности тестов на странице Моё обучение можно просмотреть результат обучения и загрузить сертификат в формате PDF.

Комментарии к статьям

Что дальше?

Одновременно с изучением курса Разработчик Bitrix Framework вам придётся обращаться к информации о других технологиях Bitrix Framework. Эта информация размещена в следующих курсах:

Для преподавания оффлайн

Если данный курс берётся в качестве основы для оффлайного преподавания, то рекомендуемая продолжительность: 5 дней (40 академических часов).

Если нет интернета

Скачать материалы курса в формате EPUB. Файлы формата EPUB Чем открыть файл на
Android:
EPUB Reader
CoolReader
FBReader
Moon+ Reader
eBoox

iPhone:
FBReader
CoolReader
iBook
Bookmate

Windows:
Calibre
FBReader
Icecream Ebook Reader
Плагины для браузеров:
EpuBReader – для Firefox
Readium – для Google Chrome

iOS
Marvin for iOS
ShortBook
обновляются периодически, поэтому возможно некоторое отставание их от онлайновой версии курса.

Использование паттерна декоратор позволяет изменить поведение и расширить функциональность уже рабочего кода не переписывая его заново. В сети можно найти достаточно много материалов описывающих синтаксис декораторов в Python, однако статей поясняющих, что же находится “под капотом”, где рассматриваются интересные примеры их применения на практике, не так уж и много. Перевод статьи Untangling Python Decorators.

В этой статье, как вы уже наверное поняли, мы займемся исследованием анатомии декораторов, использующихся при программировании на языке Python.

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

Объекты первого класса

Как вам, наверное, известно в Python практически всё является объектом, а функции рассматриваются как объекты первого класса. Это означает, что функции могут передаваться и использоваться в качестве аргументов, как и любой другой объект (например, строка, int, float, список и т. д.). Также функции можно присваивать переменным, то есть рассматривать их как любые другие объекты. Рассмотрим следующий пример:

Функции высшего порядка

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

Теперь вы можете присвоить результат выполнения функции higher другой переменной и выполнить возвращаемую ею внутреннюю функцию.

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

Замыкания

Примеры внутренних функций, определяемых в других функциях, мы разобрали в предыдущем разделе. Такие вложенные функции могут получить доступ к переменным из области видимости внешней (оборачивающей ее) функции. В Python по умолчанию предусмотрена возможность использования в функциях таких нелокальных переменных, и если мы хотим изменять их значения в коде внутренней, то должны объявить их нелокальными non-local явно (с ключевым словом nonlocal ). Ниже приведён пример вложенной функции, получающей нелокальную переменную из внешней (по умолчанию без использования ключевого слова nonlocal ).

Теперь запустим следующий код на выполнение:

Все работает так, как и было задумано. Значение параметра внешней функции name передается во внутреннюю.

Этот способ, с помощью которого, как в примере выше, строковые данные deli присоединяются к исполняемому коду, называется замыканием.

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

Значение переменной из области видимости внешней функции запоминается даже в том случае, если сама переменная выходит из текущей области видимости, а также если сама (внешняя) функция удаляется из текущего контекста исполнения (пространства имен). Декораторы в своей работе используют тот же принцип применения нелокальных non-local переменных и скоро вы убедитесь в этом сами.

Пишем декоратор сами

И так вооруживший, полученными выше, знаниями о принципе действия нелокальных non-local переменных, создадим наш первый самый простейший декоратор.

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

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

Ниже приведен результат выполнения этого кода.

В двух строках кода выше мы можем наблюдать наш простейший декоратор в действии. Функция deco принимает другую функцию в качестве своего параметра, манипулирует этой функцией внутри функции-обёртки и затем возвращает функцию-обёртку. При выполнении функции, возвращаемой нашим декоратором, вы получите модифицированный результат ее выполнения. Проще говоря, декораторы оборачивают декорируемую функцию и изменяют ее поведение, не изменяя ее кода.

Функция декоратора выполняется во время импорта/определения декорированной функции, а не при ее вызове.

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

В примере выше функция-обертка возвращает результат целевой функции и выполнения кода обертки. Этот прием позволяет получить модифицированной результат выполнения целевой функции.

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

Используем символ @ (синтаксический сахар )

Используем аргументы при декорировании функций

Определим целевую функцию, которая будет возвращать строковое значение, и которую мы далее будем декорировать.

Решение проблемы идентификации функций

В Python вы можете исследовать любой объект и его свойства с помощью интерактивной оболочки. Функция предоставляет информацию о себе, используя, например, такой способ самодокументирования кода как docstring и т. д. Исследуем информацию о встроенной функции print следующими способами:

Декораторы в дикой природе (практика)

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

Таймер

Декоратор таймер поможет измерить продолжительность во времени вызовов ваших функций простым и явным способом. Следующий пример кода применим для отладке и профайлинге Profiling пользовательских функций.

Представленным выше способом мы сможем анализировать время, необходимое для выполнения функции.

Логирование исключений

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

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

Валидация и проверки во время выполнения кода

Система типов в Python достаточно строга, но при этом весьма гибка. Несмотря на все свои преимущества, это означает, что некоторые ошибки могут все же закрасться в пользовательский код, и обычно более строго типизированные языки (такие как Java) будут отлавливать эти ошибки во время компиляции. И поэтому при написании своего кода вы захотите применять более сложные, настраиваемые проверки корректности входящих и исходящих данных. Использование декораторов поможет вам более легко справиться с этой задачей, а также применять ваши проверки к нескольким функциям одновременно.

Представьте себе, что у вас есть набор функций, каждая из которых возвращает словарь с данными, который (среди прочих полей) включает в себя поле summary (резюме, сводка). Значение этого поля не должно иметь длину свыше 30 символов, и если это не выполняется то, это будем считать ошибкой. Следующий пример кода реализует декоратор, который вызывает исключение типа ValueError, если проверка длинны поле summary не проходит:

Повторитель выполнения функций

Применяем сразу несколько декораторов

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

Используем декораторы с аргументами

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

Прежде мы сделаем это рассмотрим простой пример того, как можно определять декораторы с параметрами.

Как мы уже знаем, декоратор создает и возвращает свою внутреннюю функцию-обертку, по аналогии в декораторе repeat внутренняя функция помещается внутри другой внутренней функции. И это чем-то напоминает сон во сне из фильма «Начало».

В коде реализации функции joinby присутствует несколько важных, но неочевидных деталей:

Декораторы с аргументами и без

В этом примере параметр _func играет роль маркера, определяя, был ли декоратор вызван с параметрами или без.

Пишем универсальный шаблон для декоратора

И так, теперь нам не нужно писать три уровня вложенных функций, функция functools. partial позаботится об этом. Метод partial может быть использован для создания новых производящих функций, которым передаются некоторые входные параметры для инициализации. При этом partial будет выполнять следующий код:

Определяем декораторы с помощью классов

В этом разделе мы рассмотрим как использовать классы для создания декораторов. И так, классы могут быть очень полезны, так как позволяют избежать вложенной архитектуры при определении декораторов. Кроме того полезно использовать классы для написания декораторов с сохранением некоторого внутреннего состояния от вызова к вызову. Ниже приведен пример кода, который поясняет как можно реализовать декоратор с использованием классов.

Прежде чем мы двигаться дальше, давайте определим декоратор с сохранением состояния, используя синтаксис класса. Декораторы с сохранением состояния могут запоминать его некоторое состояние от предыдущего запуска. В примере ниже декоратор Tally с сохранением данных состояния в словаре, который следит за тем, сколько раз были вызваны декорируемые функции. Ключи этого словаря tally будут содержать имена соответствующих функций, а значения – количество их вызовов.

Еще несколько примеров

Кэширование возвращаемых значений

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

Это способ оптимизации, при котором сохраняется результат выполнения функции, а затем этот результат используется при следующем вызове, называется мемоизацией (memoization).

Представим себе следующую ситуацию, у нас в приложении используется достаточно ресурсоемкий (или с длительным временем обращения) API, и вы хотели бы, по возможности, как можно реже к нему обращаться. Идея состоит в том, чтобы сохранять и кэшировать значения, возвращаемые вызовами API для конкретных значений параметров запроса. В случае их повторного запроса с помощью API с указанными аргументами, вы могли бы просто сразу возвращать результаты из кэша вместо совершения повторного вызова методов API. Этот прием может значительно улучшить производительность вашего приложения. В примере кода ниже я смоделировал “дорогой” вызов API с использованием модуля time.

Особенностью технической реализации метода functools. lru_cache() является принцип хранения полученных ранее результатов Least Recently Used LRU, что подразумевает организацию элементов словаря в порядке их использования, что позволяет быстро определить, какой элемент не использовался в течение длительного времени.

Least recently used (вытеснение давно неиспользуемых). Из словаря с данными запросов и ответов в первую очередь, вытесняется (убираются) не использующиеся дольше всех данные. Этот алгоритм требует отслеживания того, что и когда использовалось при работе кода.

В примере кода выше параметр метода max_size определяет максимальное число возвращаемых значений, которые могут быть сохранены до того, как он начнет удалять самые ранние из них. И теперь если мы запустим функцию api() на выполнение, то увидим, что первый раз для возврата ее результата потребуется около 3 секунд. Но если вы снова запустите ее с тем же параметром, то она почти мгновенно вернет результат из своего кэша.

Преобразование единиц измерения

Следующий декоратор, который мы рассмотрим преобразует длину из единиц измерения СИ в единицы измерения других систем, не загрязняя целевую декорируемую функцию логикой преобразования.

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

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

Регистрация функции для логирования выполнения кода

Самостоятельно ознакомившись с исходным кодом фреймворка Flask, вы найдете намного больше примеров реального использования декораторов.

Небольшое дополнение

Все фрагменты кода из этой статьи были разработаны и протестированы на компьютере с Ubuntu 18.04 и Python 3.8.

Источники:

https://medium. com/nuances-of-programming/%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%B2%D0%BE%D0%B5-%D1%81%D0%BB%D0%BE%D0%B2%D0%BE-this-%D0%B8-%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BA%D1%81%D1%82-%D0%B2-javascript-6ff1561f64f5

https://dev.1c-bitrix. ru/learning/course/index. php? COURSE_ID=43&LESSON_ID=3215&LESSON_PATH=3913.4565.3215

https://www. awesomeandrew. ru/2020/06/02/%D1%80%D0%B0%D0%B7%D0%B1%D0%B8%D1%80%D0%B0%D0%B5%D0%BC%D1%81%D1%8F-%D1%81-%D0%B4%D0%B5%D0%BA%D0%BE%D1%80%D0%B0%D1%82%D0%BE%D1%80%D0%B0%D0%BC%D0%B8-%D0%B2-python/

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: