Что означает область видимости идентификатора
Область видимости объектов
Область видимости объекта (переменной или функции) определяет набор функций или модулей, внутри которых допустимо использование имени этого объекта. Область видимости объекта начинается в точке объявления объекта.
Локальные и глобальные переменные
Время жизни объекта может быть глобальным и локальным.
Глобальными называют объекты, объявление которых дано вне функции. Они доступны (видимы) во всем файле, в котором они объявлены. В течение всего времени выполнения программы с глобальным объектом ассоциирована некоторая ячейка памяти.
Локальными называют объекты, объявление которых дано внутри блока или функции. Эти объекты доступны только внутри того блока, в котором они объявлены. Объектам с локальным временем жизни выделяется новая ячейка памяти каждый раз при осуществлении описания внутри блока. Когда выполнение блока завершается, память, выделенная под локальный объект, освобождается, и объект теряет своё значение.
Результат выполнения программы
Та же программа, но с использованием глобального объекта
Результат выполнения программы
С помощью глобальных переменных можно организовать обмен информацией между функциями. При этом вызываемая функция не будет принимать значения глобальных переменных в качестве формальных аргументов. Однако в этом случае существует опасность случайного изменения глобальных объектов другими функциями.
Модификация объектов
Модификатор unsigned предназначен для того, чтобы объявлять беззнаковую целочисленную переменную, тем самым изменив диапазон представления этой переменной.
Модификатор extern предназначен для использования в данном программном модуле объекта, который объявлен в другом программном модуле.
Переменная k в функции autofunc() зафиксирована в оперативной памяти. Инициализация k проводится только один раз — при первом вызове функции. При повторном обращении к функции autofunc() инициализация переменной k не будет производиться. Значение переменной k и ее адрес сохраняются в оперативной памяти, однако эта переменная не будет доступна из других функций.
Результат выполнения программы
Модификатор register предназначен для того, чтобы поместить переменную в один из регистров общего назначения центрального процессора при наличии свободного регистра. Благодаря этому повышается скорость работы с данными. Это необходимо для создания управляющих программ, где требуется высокая скорость обработки данных.
Область видимости переменных в C++: локальные и глобальные переменные
Всем привет! Сегодня мы затронем тему, которую должны были изучить еще в самом начале пути изучения C++ — область видимости переменных. Мы разберем, что такое локальные и глобальные переменные.
Область видимости переменных в C++
Область видимости переменных — это те части программы, в которой пользователь может изменять или использовать переменные в своих нуждах.
В C++ существуют отдельные блоки, которые начинаются с открывающей скобки ( < ) и заканчиваются соответственно закрывающей скобкой ( >). Такими блоками являются циклы (for, while, do while) и функции.
Если переменная была создана в таком блоке, то ее областью видимости будет являться этот блок от его начала (от открывающей скобки — < ) и до его конца (до закрывающей скобки — >) включая все дочерние блоки созданные в этом блоке.
В примере ниже, программист ошибся с областью видимости:
А вот ошибки в строке 6 нет, поскольку второй цикл находится в первом цикле (является дочерним блоком первого цикла) и поэтому переменная b может спокойно там использоваться.
Глобальные переменные в C++
Глобальными переменными называются те переменные, которые были созданы вне тела какого-то блока. Их можно всегда использовать во всей вашей программе, вплоть до ее окончания работы. В примере ниже мы создали две глобальные переменные global и global_too и использовали их в функции summa :
Вот, что выведет данная программа:
Как видите глобальные переменные видны везде. В нашем примере внутри функции summa мы не создавали ни какие переменные, мы лишь использовали две глобальные переменные, которые были созданы раньше.
Локальные переменные
Локальные переменные — это переменные созданные в блоках. Областью видимости таких переменных является блоки ( и все их дочерние ), а также их область видимости не распространяется на другие блоки. Как ни как, но эти переменные созданы в отдельных блоках.
Из этого можно сделать вывод: у нас есть возможность создавать переменные с одинаковыми именами, но в разных блоках (или другими словами, чтобы их область видимости не совпадала друг с другом).
Нужно запомнить! Если вы создали локальную переменную, то вы должны понимать, что использование ее в других блоках будет невозможным.
Глобальная переменная уступает локальной
Если мы создадим глобальную переменную и с таким же именем локальную, то получится, что там где была создана локальная переменная будет использоваться именно локальная переменная, а не глобальная. Так как локальная переменная считается по приоритету выше глобальной. Давайте разберем, как это работает на примере ниже:
А вот, если мы вызовем функцию sait_message то результатом будет:
Вот так глобальная переменная уступает локальной!
Мы советуем вам не создавать переменные с одинаковыми именами, поскольку в будущем вам будет тяжело разобраться в коде, если там будут присутствовать одинаковые переменные.
Глобальный оператор разрешения
В случае создания двух переменных с одинаковым именем (одна из которых является глобальной, а другая локальной) при использовании в блоке, в котором была объявлена локальная переменная, можно использовать и глобальную переменную. Для ее использования нужно всего лишь применить глобальный оператор разрешения.
Глобальный оператор разрешения — это два подряд поставленные двоеточия, с помощью которых мы говорим компилятору, что хотим использовать глобальную переменную, а не локальную.
Чтобы использовать глобальный оператор разрешения нужно применять данную конструкцию:
Области видимости в JavaScript
В JavaScript область видимости — это важная, но неоднозначная концепция. Области видимости, при правильном подходе к их использованию, позволяют применять надёжные шаблоны проектирования, помогают избежать нежелательных побочных эффектов в программах. В этом материале мы проанализируем различные типы областей видимости в JavaScript, поговорим о том, как они работают. Хорошее понимание этого механизма позволит вам улучшить качество кода.
Картинка по запросу «области видимости». Извините, если вызвали приступ ностальгии )
Элементарное определение области видимости выглядит так: это область, где компилятор ищет переменные и функции, когда они ему нужны. Думаете, что звучит это слишком просто? Предлагаем разобраться вместе.
Интерпретатор JavaScript
Прежде чем говорить об областях видимости, нужно обсудить интерпретатор JavaScript, рассмотреть то, как он воздействует на различные области видимости. При исполнении JS-кода интерпретатор проходится по нему дважды.
Первый проход по коду, называемый ещё проходом компиляции — это то, что наиболее сильно воздействует на области видимости. Интерпретатор просматривает код в поисках объявлений переменных и функций и поднимает эти объявления в верхнюю часть текущей области видимости. Важно отметить, что поднимаются только объявления переменных, а операции присвоения остаются как есть — для следующего прохода, называемого проходом исполнения.
Для того, чтобы лучше это понять, рассмотрим простой фрагмент кода:
Этот код, после компиляции, будет выглядеть примерно так:
Здесь надо обратить внимание на то, что объявления поднимаются в верхнюю часть их текущей области видимости. Это, как будет видно ниже, очень важно для понимания областей видимости в JavaScript.
Лексическая область видимости
Второй проход интерпретатора — это тот, в ходе которого выполняется присвоение значений переменным и исполняются функции. В вышеприведённом примере кода именно во время этого прохода выполняется вызов bar() в строке 12.
Интерпретатору нужно найти объявление bar прежде чем выполнить этот вызов, делает он это, начиная с выполнения поиска в текущей области видимости. В тот момент текущей является глобальная область видимости. Благодаря первому проходу, то есть компиляции, мы знаем, что объявление bar находится в верхней части кода, поэтому интерпретатор может найти его и выполнить функцию.
В целом, можно сказать, что смысл лексической области видимости заключается в том, что область видимости определяется после компиляции, и когда интерпретатору надо найти объявление переменной или функции, сначала он смотрит в текущей области видимости, но, если найти то, что ему нужно, не удаётся, он переходит в родительскую область видимости, продолжая поиск по тому же принципу. Самый высокий уровень, на который он может перейти, называется глобальной областью видимости.
Затенение переменных — это шаблон проектирования, который может быть полезен в том случае, если нужно замаскировать некоторые переменные и предотвратить доступ к ним из конкретных областей видимости. Надо сказать, что я обычно избегаю использования этого приёма, применяя его только если без него совершенно невозможно обойтись, так как я уверен в том, что использование одинаковых имён переменных ведёт к путанице при командной разработке. Использование затенения способно привести к тому, что разработчик может решить, что в переменной хранится не то, что в ней на самом деле есть.
Функциональная область видимости
Как мы видели, рассматривая лексическую область видимости, интерпретатор объявляет переменные в текущей области видимости, что означает, что переменные, объявленные в функции, объявлены в функциональной области видимости. Эта область видимости ограничена самой функцией и её потомками — другими функциями, объявленными внутри этой функции.
К переменным, объявленным в функциональной области видимости, нельзя получить доступ извне. Это очень мощный шаблон проектирования, который можно задействовать, если вы хотите создать приватные свойства, и иметь к ним доступ только внутри функциональной области видимости. Вот как это выглядит:
Блочная область видимости
Блочная область видимости похожа на функциональную, но она ограничена не функцией, а блоком кода.
Немедленно исполняемые функциональные выражения
IIFE — это весьма популярный шаблон проектирования JavaScript, который позволяет функции создать новую блочную область видимости. IIFE — это обычные функциональные выражения, которые мы исполняем сразу после того, как они будут обработаны интерпретатором. Вот пример IIFE:
IIFE, кроме того, очень полезны, если вы выполняете асинхронную операцию и хотите сохранить состояние переменных в области видимости IIFE. Вот пример подобного поведения:
Причина этого в том, что к тому времени, как истечёт 1000 миллисекунд, выполнение цикла for завершится и счётчик i окажется равным 5.
Для того, чтобы код работал так, как ожидается, выводил последовательность чисел от 0 до 4, нам нужно использовать IIFE для сохранения необходимой нам области видимости:
Итоги
Мы рассмотрели различные области видимости в JavaScript, поговорили об их особенностях, описали некоторые простые шаблоны проектирования. На самом деле, об областях видимости в JavaScript можно ещё говорить и говорить, однако я полагаю, что этот материал даёт хорошую базу, воспользовавшись которой, вы сможете самостоятельно углубить и расширить ваши знания.
Надеюсь, этот рассказ помог вам лучше понять области видимости в JavaScript, а значит, улучшить качество ваших программ. Также можем порекомендовать для прочтения эту публикацию на Хабре.
Уважаемые JS-разработчики! Просим вас поделиться интересными приёмами работы с областями видимости в JavaScript.
JavaScript: область видимости простыми словами
Доброго времени суток, друзья!
Область видимости — важная концепция, определяющая доступность переменных. Данная концепция лежит в основе замыканий, разделяя переменные на глобальные и локальные.
В этой статье я постараюсь простыми словами объяснить, что такое область видимости в JavaScript.
1. Область видимости
Перед тем, как погружаться в детали, связанные с областью видимости, рассмотрим небольшой пример.
Допустим, мы определили переменную:
Мы легко можем вывести ее значение в консоль. Это понятно.
Теперь поместим объявление переменной message в блок if:
На этот раз при попытке доступа к переменной выбрасывается исключение ReferenceError: message is not defined.
Почему это произошло?
Потому что блок if создал область видимости для переменной message. И message доступна только внутри этой области.
Таким образом, доступность переменных ограничена областью видимости, в которой они определены.
Итак, область видимости — это зона доступности переменных.
2. Блочная область видимости
Блок кода в JavaScript определяет область видимости переменных, объявленных с помощью ключевых слов const и let:
Первый console.log() благополучно выводит значение переменной message в консоль, поскольку доступ к этой переменной осуществляется в той области видимости, в которой она определена.
Однако вызов второго console.log() приводит к возникновению ошибки, поскольку переменная message недоступна во внешней по отношению к ней области видимости: в текущем контексте message не существует.
В инструкциях if, for, while также создается блочная область видимости.
Переменные color и message существуют только внутри блока for.
Тоже самое справедливо для инструкции while:
message, определенная в while, доступна только внутри данного цикла.
В JavaScript вы можете создавать самостоятельные блоки кода. Они также определяют собственную область видимости:
2.1. var не имеет блочной области видимости
Как мы видели в предыдущих примерах, блок кода создает область видимости для переменных, объявленных с помощью ключевых слов const и let. Однако это не работает для переменных, объявленных с помощью ключевого слова var.
Переменная count, как и ожидалось, доступна внутри блока if. Однако, она доступна и за пределами данного блока!
Дело в том, что блок кода не создает области видимости для переменных, объявленных с помощью ключевого слова var. Но это делает функция.
3. Область видимости функции
Функции в JavaScript создают область видимости для всех переменных, независимо от того, с помощью какого ключевого слова они объявлены (var, const или let).
Функция run() создает область видимости. Переменная message доступна внутри функции, но недоступна снаружи.
Аналогичным образом функция создает область видимости для переменных, объявленных с помощью const и let, и даже для других функций и функциональных выражений:
4. Область видимости модуля
Модули ES6 также создают область видимости для переменных, функций и классов.
Модуль circle создает константу pi (для внутреннего использования):
Переменная pi объявляется внутри модуля circle и не экспортируется из него.
Затем модуль circle импортируется:
Переменная pi недоступна за пределами модуля circle (до тех пор, пока она не будет экспортирована с помощью export).
Модульная область видимости инкапсулирует модули. Это означает, что частные переменные (которые не экспортируются) используются для собственных нужд модуля и защищены от доступа извне.
Таким образом, можно сказать, что область видимости — это механизм инкапсуляции для блоков кода, функций и модулей.
5. Области видимости могут быть вложенными
Интересной особенностью областей видимости является то, что они могут быть вложены одна в другую.
В следующем примере функция run() создает область видимости, а внутри нее блок if создает еще одну область:
Область видимости блока if вложена в область видимости функции run().
Область видимости, находящаяся внутри другой области, называется внутренней областью видимости. В приведенном примере — это область видимости блока if.
Область видимости, содержащая другую область, называется внешней областью видимости. В приведенном примере — это область видимости фукнции run().
Что насчет доступности переменных? Нужно запомнить простое правило:
Переменные из внешней области видимости доступны во внутренней области.
Поэтому переменная message доступна внутри блока if.
6. Глобальная область видимости
Глобальная область видимости является самой внешней областью. Она доступна для любой внутренней или локальной области видимости. В браузере глобальной является область видимости, создаваемая при загрузке JavaScript-файла, указанного в атрибуте src тега script:
Область видимости и контекст выполнения в JavaScript
В этой статье познакомимся с таким понятием как область видимости переменных и функций. Рассмотрим доступ к каким переменным и функциям мы имеем из разных мест кода.
Область видимости (scope). Цепочка областей видимости
Область видимости определяет доступность (видимость) переменных и функций вида Function Declaration.
Области видимости создаются во время выполнения JavaScript программы (сценария).
В языке JavaScript (до ES6) выделяют 2 области видимости:
Локальная или функциональная область видимости создаётся во время вызова функции. При этом локальная область у каждого вызова функции, даже одной и той же, будет своя.
В приведённом примере во время вызова функции outputNum будет создана локальная область, а также установлено в качестве значения [[Scope]] область в которой данная функция была объявлена.
В результате поиск всегда заканчивается одним из двух нижеприведённых сценариев:
Второй сценарий: интерпретатор не нашёл нужный идентификатор. В этом случае он бросает ошибку о том, что данный идентификатор не определён. Данный сценарий может возникнуть только тогда, когда интерпретатор в поиске переменной или функции дошёл до глобальной области видимости и не нашёл её в ней.
Последовательность областей видимости, которые интерпретатор использует при разрешении имени идентификатора, называется в JavaScript цепочкой областей видимости (scope chain).
В этом примере интерпретатор при разрешении переменной color дойдёт от текущей до глобальной области видимости:
В этом примере значение переменной drink будет взято из локальной области, созданной во время вызова внешней функции:
В этом примере показано то, что в глобальной области видимости нельзя обратиться к переменным и функциям, находящимся в локальной области видимости.
При разрешении имени, интерпретатор начинает поиск, начиная с текущей области видимости. Поэтому этот пример выведет в консоль текст «Дима».
Если в функции displayName не была бы объявлена переменная name, то интерпретатор не обнаружил бы её в области, созданной во время вызова этой функции. В этом случае он взял бы значение из области видимости, созданной во время вызова функции getName. В результате в консоль был бы выведен текст «Иван».
В этом примере функция f1 объявлена в глобальной области видимости. Поэтому свойство [[Scope]] функции f1, во время её вызова, будет содержать ссылку на глобальную область видимости даже несмотря на то, что данная функция вызвана в локальной области видимости, созданной во время вызова функции f2.
Поднятие (hoisting) функций и переменных
Функции вида function declaration можно использовать в JavaScript до их объявления. Это происходит из-за того что они поднимаются (hoisting) или другими словами «перемещаются» в начало текущего контекста.
Но поднятие в JavaScript выполняется не только функций вида function declaration, но и переменных, объявленных с помощью ключевого слова var. При этом поднятие осуществляется только самого объявления переменной.
Вышеприведённый код после поднятия будет аналогичен следующему:
Локальные и глобальные переменные
В JavaScript переменные, созданные в глобальной области видимости называются глобальными, а переменные созданные в локальной области видимости соответственно локальными.
Иными словами, глобальные переменные — это переменные, объявленные вне тела какой-либо функции, а локальные — это переменные, объявленные внутри тела какой-либо функции.
В JavaScript до ES6 блочных областей видимости не было. Т.е. любая переменная созданная с помощью ключевого слова var внутри блока будет видима и за его пределами.
В ES6 были введены ключевые слова let и const. Они предназначены для создания переменных и констант, видимость которых будет ограничено блоком в котором они объявлены. Блочная область видимости в JavaScript определяется посредством фигурных скобок.
Например, переменная subject не будет видна за пределами блока:
Кроме этого переменные, объявленные с помощью let и константы, созданные посредством const в JavaScript не поднимаются (hoisting). Т.е. к ним нельзя обратиться до их непосредственного объявления.
Контекст функции. Ключевое слово this
Если функция не является методом объекта, то this будет указывать на window (глобальный объект).
Если функция – это метод объекта, то this внутри тела функции будет указывать на него.
Указание контекста функции. Методы call и apply
В JavaScript можно явно указать контекст, в котором необходимо вызвать функцию.
Не в строгом режиме в этом случае this будет указывать на объект window.
В строгом режиме this будет равно null.
Привязка функции к контексту (метод bind)
Функция (метод) в JavaScript не сохраняет контекст (объект) к которому она относится.
В этом очень просто убедиться, если, например, сначала сохранить ссылку на функцию (метод) в некоторую переменную. А после этого вызвать эту функцию, используя данную переменную.
В результате вызова getModelMouse будет возвращена ошибка, т.к. контекст, к которому относится данный метод, будет потерян.
Метод bind предназначен для явной привязки контекста ( this ) к функции. Он в отличие от методов call и apply не вызывает функцию. Механизм этого метода заключается в создании функции-обёртки, которая будет устанавливать необходимый контекст целевой функции.
Кроме этого, эта функция-обёртка будет результатом, который метод bind будет возвращать в результате своего выполнения.
Метод bind также позволяет задать аргументы, которые необходимо передать функции в момент её вызова. Данные аргументы будут переданы целевой функции до аргументов, которые ей будут установлены явно при её вызове.
Синтаксис метода bind :
Например, изменим вышеприведённый пример. А именно, не просто сохраним ссылку на метод, а выполним это с привязкой его к объекту mouse:
В этом примере, рассмотрим как осуществляется передача аргументов функции, привязанной к некоторому объекту с помощью bind.
В локальной области видимости, созданной во время выполнения функции sayHi можно получить значение переменной myName, myName1 и myName2. Переменная myName находится в текущей области выполнения,
А вот в функции sayHello() доступны только 2 переменные:
Рассмотрим ещё один пример:
Функция sayHi() выведет в консоль «Привет, Дима». Это обусловлено тем, что переменная name существует в текущем контексте.
Функция sayHello() отобразит в консоли запись «Привет, Женя». Переменная name найдена в родительском (глобальном) контексте.
Ключевое слово var
Рассмотрим следующий пример:
Некоторые особенности языка JavaScript при работе с переменными и функциями
У языка JavaScript есть одна интересная особенность, которая связана с тем как браузер понимает код, в котором использование переменной идёт до её объявления.
Рассмотрим эту ситуацию на следующем примере:
В этом примере вывод значения переменной myName в консоль идёт до её объявления и инициализации.
Как браузер понимает этот код? Браузер объявления переменных всегда поднимает вверх их функциональной области видимости.
Т.е. браузер будет видеть вышепредставленный код следующим образом:
В результате в консоли отобразится сообщение «Привет, undefined».
Кроме переменных, вверх их функциональной области видимости браузер поднимает ещё функции. Т.е. код JavaScript позволяет вызвать функцию до её объявления.
Вышеперечисленные особенности языка необходимо знать и по возможности их не использовать в коде. Т.к. это может привести к тому, что код станет более трудночитаемым. В результате это может привести к ошибках.
Поэтому следует придерживаться следующих правил: