Быстрые ссылки
Глобальные переменные — тема для споров: это полезный инструмент или опасный пример неаккуратного кода? Давайте обсудим их функции, преимущества и причины, по которым стоит быть осторожным при их использовании.
Что такое глобальная переменная?
Компьютерная программа — это, по сути, набор инструкций, которые компьютер выполняет при запуске. Однако многие программы достаточно сложны, и они не укладываются в простую последовательность. Структуры, такие как блоки, функции и классы, помогают организовать код, делая его более управляемым.
Функции — это основной инструмент группировки кода, который изолирует его поведение от остальной части программы. Вы можете вызывать функцию из разных частей кода и повторно использовать одну и ту же логику, избегая дублирования.
Вот пример функции на JavaScript, использующей два типа переменных: аргумент функции и локальную переменную:
Аргумент функции x автоматически заполняется значением, переданным функции при вызове. В данном примере он равен 4.
Переменная i объявляется с помощью ключевого слова let, что гарантирует её локальную область видимости. Изначально её значение не определено, до тех пор пока цикл for не присвоит и не изменит его значение.
Каждая переменная имеет свою область видимости внутри функции факториала; никакой другой код не может читать или изменять значения x или i. Вы можете запустить этот JavaScript в консоли браузера и убедиться, что переменные x и i недоступны вне функции:
JavaScript также поддерживает глобальные переменные, которые действуют на протяжении всей программы. Вот альтернативная версия функции факториала, которая требует задать глобальную переменную перед вызовом вместо передачи аргумента:
Эта функция нарушает стандарты и на практике оказывается неэффективной; она показана лишь для демонстрации потенциального использования глобальных переменных. Она работает, но такое использование неудобно и громоздко. На самом деле, этот подход напомнит код на старом ассемблере, где концепция функций была почти отсутствующей.
Большинство языков программирования поддерживают глобальные переменные, но делают это по-разному. Например, PHP использует ключевое слово global для доступа к переменной, объявленной вне любой функции:
В приведенном коде функция inc использует ключевое слово global для получения доступа к переменной $a, объявленной на верхнем уровне. Когда она задает значение $a, это изменяет верхнюю переменную, что подтверждается выводом, равным 2. Однако $b не объявлена как глобальная внутри inc, поэтому функция изменяет только локальную переменную с тем же именем, сохраняя исходное значение верхней переменной равным 0.
Как можно неправильно использовать глобальные переменные?
Основная проблема глобальных переменных заключается в том, что они нарушают инкапсуляцию, увеличивая вероятность ошибок. Рассмотрим следующий пример:
Функция day_name() обращается к глобальному массиву для возвращения названия дня по его номеру. В небольшой программе это, вероятно, не станет проблемой, но по мере увеличения длины и сложности кода ошибки могут возникать чаще.
Поскольку переменная days является глобальной, любой другой участок кода может её изменить. Следующий код может быть добавлен в любое место и радикально изменить поведение day_name:
В крупных программах определить участки кода, использующие или изменяющие глобальные переменные, может быть сложно и времязатратно.
Эта проблема усугубляется, если ваш код многопоточный. С наличием нескольких копий вашего кода становится гораздо труднее гарантировать, что они все используют и изменяют глобальные переменные, не мешая друг другу.
Кроме того, такой код становится сильно связанным, что затрудняет его тестирование. Наличие зависимости между функцией и глобальной переменной значит, что они всегда должны существовать вместе, что усложняет тестирование функции в изоляции.
Что такое модульное тестирование и почему оно важно?
Модульное тестирование — это процесс написания и автоматического запуска тестов, чтобы убедиться, что функции, которые вы написали, работают так, как задумано.
Чем больше глобальных переменных вы используете, тем выше вероятность конфликта имён. В JavaScript это особенно актуально из-за глобального объекта. В веб-браузере все глобальные переменные хранятся как свойства объекта Window. Это означает, что есть риск объявить глобальную переменную, которая переопределяет свойство Window, которое ваш код — или чей-то чужой — считает существующим.
Вызов window.alert() завершится ошибкой, так как теперь это строка, а не функция. Хотя вы не станете писать этот код намеренно, сделать это случайно очень легко. Чем больше глобальных переменных вы используете, тем выше вероятность конфликтов с другим кодом. Вы можете попытаться избежать этого, используя более необычные имена для глобальных переменных, но это всего лишь временное решение; нет никаких гарантий, что ваш код будет безопасным.
Все эти проблемы могут стать ещё более частыми, если вы используете внешние библиотеки в зависимости от того, как ваш язык защищает вас. JavaScript предлагает мало защиты, и если вы не будете осторожны, глобальные переменные могут сломать код библиотеки, которую вы используете — или наоборот.
И для чего же нужны глобальные переменные?
Тем не менее, глобальные переменные не всегда плохи — иногда они необходимы, и избегание их любой ценой может обойтись дорого! Вот разумный пример:
Такой подход к отладке может быть полезен в процессе разработки и тестирования и вполне приемлем для малых программ. Тем не менее, он всё равно уязвим к проблемам, особенно тем, что любая часть кода может изменить значение debug; оно изменяемое. Чтобы избежать этого, лучше всего объявить переменную как константу, если вы хотите предотвратить изменение её значения:
Важно отметить, что константа в JavaScript не является строго глобальной. Во-первых, она не будет добавлена как свойство объекта window. Но константа, объявленная на верхнем уровне скрипта, будет доступна всему коду, который идёт за ней.
Let, Var и Const: определение переменных в JavaScript
Завершение ES6 в 2015 году привнесло новые способы определения переменных в JavaScript.
Если вы всё же оказались в ситуации, когда используете глобальные переменные, вы можете снизить вероятность проблем, используя один глобальный объект. Например, вместо:
Вы можете хранить те же значения в глобальном объекте:
Используя этот подход, вы добавляете всего одно имя в глобальное пространство, что означает меньше шансов на конфликт с другими переменными, и облегчает поиск кода, использующего эту переменную.
Наконец, документация — ваш союзник. Если вам нужно использовать глобальные переменные, убедитесь, что они задокументированы в комментариях, особенно если вы рассматривали альтернативный подход, но в итоге отклонили его. Имена переменных также служат документацией, поэтому убедитесь, что вы используете чёткие, лаконичные и информативные имена, которые объясняют назначение каждой переменной.
Если вам понравилась эта статья, подпишитесь, чтобы не пропустить еще много полезных статей!
Вы также можете читать наши материалы в:
- Telegram: https://t.me/gergenshin
- Яндекс Дзен: https://dzen.ru/gergen
- Официальный сайт: https://www-genshin.ru