Содержание
Область видимости в Javascript
В этом уроке мы с вами поговорим о глобальных и локальных переменных. А именно, об области видимости переменных.
И это все зависит от того, где вы создаете переменную. Когда вы создаете переменную в javascript, то она становится глобальной переменной, так как попадает в глобальную область видимости.
var name = 'Alex'
Это глобальная переменная
Если же мы создадим переменную внутри функции, то она станет локальной переменной функции. Эьл значит, что она будет доступна только внутри функции, а снаружи ее не будет видно.
var name = 'Alex'
function getName () {
var otherName = 'John'
}
Давайте попробуем вывести переменную name.
var name = 'Alex'
function getName () {
var otherName = 'John'
}
document.write(name)
Как мы видим, эта переменная вывелась, так как она доступна нам в глобальной области видимости.
Если же мы попробуем вывести переменную otherName, то оно ее не выведет, так как эта переменная доступна только внутри функции
var name = 'Alex'
function getName () {
var otherName = 'John'
}
document.write(otherName)
Давайте перенесем document.write внутрь функции getName и вызовем эту функцию ниже
var name = 'Alex'
function getName () {
var otherName = 'John'
document.write(otherName)
}
getName()
Тепрь у нас в браузер вывелась переменная otherName. Это происходит потому, что document.write теперь имеет доступ к всем локальным переменным внутри функции.
Теперь давайте разберем нюансы. В javascript можно создать переменную не используя слово var
someText = 'text'
И javascript прочитает эту инструкцию абсолютно спокойно. Единственный нюанс в том, что эта переменная будет всегда обьявлена как глобальная. В если случаи когда это очень сильно усложняет понимание кода
Если мы напишем document.write в конце кода и попробуем вывести опять otherName, то у нас ничего не выведет, так как такой переменной нет в глобальной области видимости.
var name = 'Alex'
function getName () {
var otherName = 'John'
}
getName()
document.write(otherName)
Если же мы уберем var и создадим переменную без него, то переменная станет глобальная и document.write выведет ее нам
var name = 'Alex'
function getName ()
getName()
document.write(otherName)
Никогда в жизни так не пишите. Это абсолютно не однозначно и сразу же усложняет понимание кода. Всегда создавайте все переменные только с var. В этом случае, переменная становится глобальной, хотя возможно мы хотели сделать ее локальной. И в любом другом месте мы можем ее переопределить, даже не подозревая об этом.
И еще один нюанс. Все глобальные переменные существуют, пока у нас загружена страница. Если мы ее перезагрузим, то все сотрется.
Локальные же переменные исчезнут, как только функция которую мы вызвали закончит выполнятся. В нашем случае, переменная otherName исчезнет, как только функция getName закончит выполнение.
Если у вас возникли какие-то вопросы или комментарии, пишите их прямо под этим видео.
Область | Учебник JavaScript | schoolsw3.com
На сайте нет рекламы
Область видимости определяет доступность (видимость) переменных.
Область действия функции JavaScript
В JavaScript есть два типа области видимости:
- Локальный охват
- Глобальный охват
JavaScript имеет область действия: каждая функция создает новую область видимости.
Область действия определяет доступность (видимость) этих переменных.
Переменные, определенные внутри функции, недоступны (видимы) снаружи функции.
Локальные переменные JavaScript
Переменные, объявленные в функции JavaScript, становятся ЛОКАЛЬНЫМИ для функции.
Локальные переменные имеют область действия: к ним можно получить доступ только из функции.
Поскольку локальные переменные распознаются только внутри своих функций,
переменные с одинаковыми именами могут использоваться в разных функциях.
Локальные переменные создаются при запуске функции и удаляются, когда функция завершается.
Глобальные переменные JavaScript
Переменная, объявленная вне функции, становится ГЛОБАЛЬНОЙ.
Глобальная переменная имеет глобальную область действия:
все сценарии и функции на веб-странице могут получить к ней доступ.
Переменные JavaScript
В JavaScript объекты и функции также являются переменными.
Область видимости определяет доступность переменных, объектов и функций из разных частей кода.
Автоматически глобальный
Если вы присвоите значение переменной, которая не была объявлена, она автоматически станет ГЛОБАЛЬНОЙ переменной.
В этом примере кода будет объявлена глобальная переменная carName
,
даже если значение присвоено внутри функции.
Строгий режим
Все современные браузеры поддерживают выполнение JavaScript в «строгом режиме».
Вы узнаете больше о том, как использовать строгий режим в следующей главе этого руководства.
В «строгом режиме» необъявленные переменные не становятся глобальными автоматически.
Глобальные переменные в HTML
В JavaScript глобальная область видимости — это полная среда JavaScript.
В HTML глобальной областью видимости является объект окна. Все глобальные переменные принадлежат объекту окна.
Предупреждение
НЕ создавайте глобальные переменные, если вы этого не собираетесь.
Ваши глобальные переменные (или функции) могут перезаписывать переменные окна (или функции).
Любая функция, включая объект окна, может перезаписать ваши глобальные переменные и функции.
Время жизни переменных JavaScript
Время жизни переменной JavaScript начинается с момента ее объявления.
Локальные переменные удаляются по завершении функции.
В веб браузере глобальные переменные удаляются при закрытии окна (или вкладки) браузера.
Аргументы функции
Аргументы (параметры) функции работают как локальные переменные внутри функций.
JavaScript. Переменные (глобальные, локальные, константы)
Переменные и константы в JavaScript. Объявление переменных и присвоение им значений. Переменные глобальные и локальные. Использование констант.
Объявление переменных в JavaScript
Имена переменных в JavaScript могут состоять из букв, цифр, знака $ и знака _, причем имя переменной не может начинаться с цифры. Имейте в виду, что JavaScript чувствителен к регистру букв, и переменные a1 и A1 – это разные переменные. Кириллицу использовать не рекомендуется, хотя это возможно.
Переменные в JavaScript объявляются ключевым словом var:
var Peremennaya_1 var Peremennaya_2 |
Использовать переменные в JavaScript без объявления не рекомендуется. Это возможно, но может привести к ошибкам.
Присвоение значения переменным
Присвоение значения объявленным переменным в JavaScript:
Peremennaya_1 = 25 Peremennaya_2 = «Присваиваемый текст заключаем в прямые кавычки» |
Можно присваивать значение переменным сразу при объявлении:
var Peremennaya_1 = 25 var Peremennaya_2 = «Присваиваемый текст заключаем в прямые кавычки» |
Значение переменной в JavaScript может изменяться в процессе выполнения программы. При записи в переменную текста, его необходимо заключить в прямые кавычки.
Переменные локальные и глобальные
Если переменная объявлена внутри функции, то она является локальной и будет доступна (иметь видимость) только в пределах этой функции. При выходе из функции локальные переменные в JavaScript уничтожаются, поэтому в разных функциях можно использовать переменные с одним и тем же именем.
Если переменная объявлена вне функций, то она является глобальной и будет доступна (иметь видимость) во всех функциях в пределах страницы. Глобальные переменные уничтожаются в JavaScript при закрытии страницы.
Константы в JavaScript
Константы предназначены для упрощения работы с кодом, когда приходится использовать повторяющиеся значения или выражения. Достаточно однократно задать константе значение и можно сколько угодно его использовать, вставляя в код своих программ. В JavaScript нет ключевого слова для объявления констант, вместо констант используются обычные переменные. Чтобы константы отличались от переменных, их принято обозначать заглавными буквами, при необходимости используя знак подчеркивания:
var DRUG_CHELOVEKA = «Собака» |
Приведенный пример константы не совсем полноценный, так как слово «Собака» и так несложно запомнить и вставлять куда нужно. Использовать константы в JavaScript можно для записи и вставки более сложных значений, например, трудно запоминаемых кодов, наборов символов, длинного текста, веб-адресов, адресов электронной почты, телефонных номеров, различных коэффициентов.
В JavaScript константы можно перезаписывать, как переменные, но если это делать, тогда теряется смысл констант.
Замыкания в JavaScript — Блог HTML Academy
Замыкания являются ключевой особенностью в JavaScript, которую каждый уважающий себя программист должен знать.
В интернете есть множество объяснений того, что из себя представляют замыкания, но мало кто рассказывает, почему они такие.
Разработчикам понимание принципов работы тех или иных особенностей языка, даст больше осознанности в их применении, поэтому этот пост посвящён внутреннему устройству замыканий: как они работают и почему.
Надеюсь, после этой статьи вы будете лучше подготовлены к использованию замыканий в своей повседневной разработке. Давайте начнём.
Что такое замыкания?
Замыкания являются мощным инструментом в JavaScript и других языках программирования. Вот определение с MDN:
Замыкания — это функции, ссылающиеся на независимые (свободные) переменные. Другими словами, функция, определённая в замыкании, «запоминает» окружение, в котором она была создана.
Заметка: cвободные переменные — это переменные, которые не объявлены локально и не передаются в качестве параметра.
Давайте посмотрим на несколько примеров:
Пример 1
В примере функция numberGenerator
создаёт локальную «свободную» переменную num (число) и checkNumber (функция, которая выводит число в консоль). Функция checkNumber не содержит собственной локальной переменной, но благодаря замыканию она имеет доступ к переменным внутри внешней функции, numberGenerator. Поэтому объявленная в numberGenerator переменная num будет успешно выведена в консоль, даже после того, как numberGenerator вернёт результат выполнения.
Пример 2
В этом примере видно, что замыкания содержат в себе все локальные переменные, которые были объявлены внутри внешней замкнутой функции — enclosing function.
Обратите внимание, как переменная hello определяется после анонимной функции, но эта функция всё равно может получить доступ к этой переменной hello. Это происходит из-за того, что переменная hello во время создания уже была определена в области видимости (scope), тем самым сделав её доступной на тот момент, когда анонимная функция будет выполнена. Не беспокойтесь, позже я объясню, что такое «область видимости». А пока просто смиритесь с этим.
Понимаем высокий уровень
Наши примеры показали нам, почему замыкания находятся на высоком уровне. Главная мысль такая: мы имеем доступ к переменным, которые были определены в замкнутых функциях и описывают их переменные как возвращённые. Также что-то происходит в фоновом режиме, что делает эти переменные доступными после замкнутых функций, которые определяют и возвращают их.
Чтобы понять, как это работает, давайте рассмотрим несколько связанных между собой идей. Мы зайдём издалека и постепенно вернёмся к замыканиям. Начнём наш путь с общего контекста, в котором выполняется функция, и известного как контекст выполнения — execution context.
Замыкания — только часть продвинутого JavaScript
Пройдите курс «JavaScript. Архитектура клиентских приложений» и прокачайте свои навыки. Скидка —1000 ₽ по промокоду SKUCHNO.
Класс, расскажите
Нажатие на кнопку — согласие на обработку персональных данных
Контекст выполнения
Контекст выполнения — это абстрактное понятие, которое используется в спецификации ECMAScript для оценки времени выполнения кода. Это может быть глобальный контекст — global context, в котором ваш код выполнится первым, или когда поток выполнения переходит в тело функции.
В любой момент времени выполняется только один контекст функции (тело функции). Вот почему JavaScript является однопотоковым, так как единовременно может выполняться только одна команда. Обычно браузеры поддерживают этот контекст с помощью стека — stack. Стек — структура данных, выполняемая в обратном порядке: LIFO — «последним пришёл — первым вышел». Последнее, что вы добавили в стек, будет удалено первым из него. Это происходит из-за того, что мы можем только добавить или удалить элементы из верхушки стека. Текущий или «выполняющийся» контекст исполнения — всегда верхний элемент стека. Он выскакивает из стека, когда код в текущем контексте полностью разобран, позволяя следующему верхнему элементу стека взять на себя контекст выполнения.
Кроме того, если контекст уже выполняется, это не означает, что ему нужно завершить своё выполнение, прежде чем другой контекст выполнения сможет начать работу. Бывают случаи, когда контекст приостанавливается и другой контекст начинает работу. Прерванный контекст может быть позже забран обратно наверх в том месте, где он был приостановлен. В любое время один контекст может быть заменён другим, и этот новый контекст поместится в стек, став текущим контекстом выполнения.
Для наглядности запустите в консоли код, который вы видите ниже:
Затем, когда boop возвратится, он удалится из стека, и bar продолжит работу:
Когда у нас есть целая куча контекстов исполнения, выполняющиеся один за другим и останавливающиеся в середине выполнения и снова запускающиеся, то нужно как-то отслеживать их состояние, чтобы мы могли управлять последовательностью выполнения этих контекстов. Согласно спецификации ECMAScript, каждый контекст выполнения имеет различные компоненты, которые используются для отслеживания прогресса исполнения кода. К ним относятся:
- Оценка состояния кода — любое состояние необходимо выполнить, приостановить и возобновить определение кода, связанного с этим контекстом выполнения.
- Функция — объект функции, который оценивает контекст выполнения или null, если контекст был определён как script или модуль.
- Область — набор внутренних объектов, глобальное окружение ECMAScript, весь код ECMAScript, который находится в пределах этого глобального окружения и другие связанные с ним состояния и ресурсы.
- Лексическое окружение — используется для разрешения ссылок идентификатора кода в этом контексте исполнения.
- Переменное окружение — лексическое окружение, чья запись окружения — EnvironmentRecord имеет связи, созданные заявленными переменными — VariableStatements в этом контексте выполнения.
Не волнуйтесь, если это звучит слишком сложно. Из всех переменных, переменные лексического окружения наиболее интересны для нас, ведь они явно указывают, что принимают идентификатор ссылки кода в этом контексте выполнения. Вы можете думать о «идентификаторах» как о переменных. Так как наша первоначальная цель состояла в том, чтобы выяснить, как это возможно, что мы получаем доступ к переменным даже после того, как функция или «контекст» была возвращена, то мы должны копнуть ещё глубже в лексическую область видимости.
Заметка: c технической точки зрения, окружение переменных и лексическая область видимости используются для реализации замыканий. Но для простоты мы заменим его на «окружение». Для детального объяснения разницы между лексическим и переменным окружением читайте статью Акселя Раушмайера.
Лексическая область видимости
Дадим определение: лексическое окружение — специфичный тип, используемый для связи идентификаторов с определёнными переменными и функциями на основе лексической структуры вложенности кода ECMAScript. Лексическое окружение состоит из записи окружения и, возможно, нулевой ссылки на внешнее лексическое окружение. Обычно лексическое окружение связано с определённой синтаксической структурой, например: FunctionDeclaration — объявление функции, BlockStatement — оператор блока, Catch clause — условный оператор, TryStatement — перехват ошибок и новым лексическим окружением, которое создавалось каждый раз при разборе кода. — ECMAScript-262/6.0
Давайте разберём это.
- «используемый для связи идентификаторов»: целью лексического окружения является управление данными, то есть идентификаторами в коде. Говоря иначе, это придаёт им смысл. Например, у нас есть такая строка в консоли: console.log(x / 10), x здесь бессмысленная переменная или идентификатор без чего-либо, что придавало бы ей смысл. Лексическое окружение обеспечивает смысл или «ассоциацию» через запись окружения. Смотрите ниже.
- Лексическое окружение состоит из записи окружения: запись окружения — причудливый способ сказать, что она хранит записи всех идентификаторов и связей, которые существуют в лексической области видимости. Каждая лексическая область видимости имеет собственную запись окружения.
- Лексическая структура вложенности: самый интересный момент, который говорит, что внутреннее окружение ссылается на внешнее окружение, и это внешнее окружение может иметь собственное внешнее окружение. В результате окружение может быть внешним окружением для более чем одного внутреннего окружения. Глобальное окружение является единственным лексическим окружением, которое не имеет внешнего окружения. Это сложно описать словами, поэтому давайте использовать метафоры и представим лексическое окружение как слои лука: глобальная среда — внешний слой луковицы, где каждый последующий слой находится ниже.
Так выглядит окружение в псевдокоде:
- Новое лексическое окружение, которое создавалось каждый раз при разборе кода — каждый раз, когда вызываются внешние вложенные функции, создаётся новое лексическое окружение. Это важно, и мы вернёмся к этому моменту в конце. Примечание: функции — не единственный способ создать лексическое окружение. Другие типы содержат в себе оператор блока — block statement или условный оператор — catch clause. Для простоты, я сосредоточусь на окружении созданной нами функции на протяжении всего поста.
Каждый контекст исполнения имеет собственное лексическое окружение. Это лексическое окружение содержит переменные и связанные с ними значения, а также имеет ссылку на него во внешнем окружении. Лексическое окружение может быть глобальным окружением, модульным окружением, которое содержит привязку для объявлений модуля на высшем уровне, или окружением функций, где окружение создаётся за счёт вызова функции.
Цепочки областей видимости
Исходя из приведённого выше определения, мы знаем, что окружение имеет доступ к окружению своего родителя, его родительское окружение имеет доступ к своему родительскому окружению и так далее. Этот набор идентификаторов, к которому каждое окружение имеет доступ, называется область видимости — scope. Мы можем вложить их в иерархические цепочки окружения, известные как цепочки областей видимости.
Давайте рассмотрим эту структуру вложенности:
Как вы можете видеть, bar вложен в foo. Чтобы всё это представить посмотрите на диаграмму ниже:
Мы вернёмся позже к этому примеру.
Эта цепочка области видимости или цепочка окружения связанная с функцией сохраняется в объекте функции в момент создания. Другими словами, она определяется статично по местоположению в исходном коде. Это называют лексической областью видимости.
Давайте быстренько разберём разницу между динамической областью видимости и статической областью видимости. Это поможет нам разобраться, почему статическая область видимости или лексическая область видимости необходима для использования замыкания.
Идём в обход: динамическая область видимости против статической области видимости
У динамических языков программирования существует стековая архитектура — stack-based implementations, локальные переменные и функции хранятся в стеке. Поэтому, во время выполнения стека, программа определяет какую переменную вы имеете в виду. С другой стороны, статическая область видимости — это когда переменные ссылаются на контекст и фиксируются на момент создания. Другими словами, структура исходного кода программы определяет к каким переменным вы обращаетесь.
Вы могли задаваться вопросом, как различаются динамическая и статическая области видимости. Вот два примера, которые помогут это продемонстрировать:
Пример 1
Как мы видим из примера выше, статическая и динамическая область видимости возвращают разные значения при вызове функции bar.
В статической области видимости возврат значения bar зависит от значения x. Это происходит из-за того, что статическая и лексическая структура исходного кода приводит x и к 10, и к 15.
Динамическая область видимости даёт нам стек определённых переменных, которые отслеживаются во время выполнения. Поэтому x, которую мы используем, зависит от того, что находится в её области видимости и как она была динамично определена во время выполнения. Выполнение функции bar выталкивает x = 2
на верхушку стека, заставляя foo вернуть 7.
Пример 2
Аналогично и в динамической области видимости. Переменная myVar решает, какое использовать значение myVar в зависимости от того, где была вызвана функция. Статическая область видимости приводит myVar к переменной, которая была сохранена в рамках двух немедленно вызываемых функций при их создании.
Как вы можете заметить, динамическая область видимости часто создаёт некоторую двусмысленность. Она не даёт точно понять, какая свободная переменная будет передана.
Замыкания
Вы можете подумать, что всё, о чём мы говорим, совершенно не касается нашей темы, но на самом деле мы разобрали всё, что поможет нам понять замыкания:
Каждая функция имеет контекст выполнения, который состоит из окружения и передаёт смысл в переменные этой функции и ссылку на окружение своего родителя. Эта ссылка делает все переменные в родительской области доступными для всех внутренних функций, независимо от того, вызывается ли внутренняя функция (или функции) вне или внутри области видимости, в которой они были созданы.
Кажется, как будто функция «запоминает» это окружение, поскольку функция буквально имеет ссылку к области видимости и переменным, определённым в этой среде.
Возвратимся к примеру вложенной структуры:
Основываясь на нашем понимании того, как работает окружение, мы можем сказать, что определение окружения для вышеупомянутого примера выглядит примерно так в псевдокоде:
Когда мы вызываем функцию test, мы получаем 45, и она возвращает значение из вызова функции bar (потому что foo возвращает bar). bar имеет доступ к свободной переменной y даже после того, как функция foo вернётся, так как bar имеет ссылку на y через его внешнее окружение, которое является окружением foo! bar так же имеет доступ к глобальной переменной x потому, что у окружения foo есть доступ к глобальному окружению. Это называют «поиск цепочки области видимости».
Подведём итог обсуждения динамической области видимости против статической: для замыканий, которые будут выполняться, нельзя использовать динамическую область с помощью динамического стека. Это сохранит наши переменные. Причина такого поведения кроется в том, что когда функция возвращается, переменные будут удалены из стека и больше не будут доступны, а это противоречит нашему определению замыкания. Это происходит из-за того, что замкнутость данных в родительском контексте сохраняется в так называемой «куче», и это позволяет сохранять данные после вызова функции, делая их возможными для возврата, то есть даже после того, как контекст выполнения извлекается из стека выполнения вызова.
Теперь, когда мы понимаем внутренности на абстрактном уровне, давайте рассмотрим ещё пару примеров:
Пример 1
Вот типичное заблуждение: в цикле for мы пробуем связать переменную счётчика с какой-либо функцией.
На основе всего что было ранее, мы можем с лёгкостью найти ошибку здесь. Абстрактно говоря, вот так выглядит окружение, во время выхода из цикла for:
Было бы неверно предполагать, что область видимости отличается для всех пяти функций в результирующем массиве. Вместо того, что происходит по факту, окружение или контекст/область видимости является тем же самым для всех пяти функций в пределах результирующего массива. Поэтому каждый раз, когда переменная i увеличивается, обновляется область видимости, а она является общей для всех функций. Из-за этого любая из пяти функций, пытающихся получить доступ к i, возвращает 5, i равна 5, когда цикл завершается.
У нас есть только один способ исправить это — создать дополнительный вызываемый контекст для каждой функции, чтобы у них появился собственный контекст/область видимости.
Ура, мы исправили это.
Есть ещё одно решение, в котором мы используем let вместо var, let находится в операторе блока и поэтому новая привязка идентификатора замыкания создаётся для каждой итерации в цикле for.
Та-дам!
Пример 2
В этом примере мы покажем как каждый вызов в функции создаёт новое отдельное замыкание:
Мы видим что каждый вызов в функции iCantThinkOfAName создаёт новое замыкание, а именно foo и bar.
Последующие вызовы каждой замкнутой функции обновляют замкнутые переменные в пределах самого замыкания, демонстрируя, что переменные в каждом замыкании используются функции iCantThinkOfAName’s doSomething после того, как вернулась iCantThinkOfAName.
Пример 3
Обратите внимание, что mysteriousCalculator находится в глобальной области и возвращает две функции. Говоря иначе, окружение для кода выше будет выглядеть так:
Это происходит из-за того, что наши функции add и substract ссылаются на среду mysteriousCalculator, и они в состоянии использовать переменные этой среды для расчёта результата.
Пример 4
Последний пример продемонстрирует важность использования замыканий: для поддержания собственной ссылки на переменную во внешней области видимости.
Это очень мощная техника — она даёт замыкающей функции guessPassword исключительный доступ к переменной password, делая невозможным доступ к password снаружи.
Tl;dr
- Контекст выполнения — это абстрактный контекст, использовавшийся в спецификации ECMAScript для отслеживания времени выполнения кода. В любое время может быть только один контекст выполнения, который выполняет код.
- Каждый контекст исполнения имеет лексическое окружение. Оно содержит связи идентификаторов, то есть переменные и их значения и имеет ссылку на него во внешнем окружении.
- Набор идентификаторов, к которым у каждого окружения есть доступ, называют «область видимости». Мы можем вложить эти области в иерархическую цепь окружения, известной как «цепочки области видимости».
- Каждая функция имеет контекст выполнения, который включает в себя лексическое окружение. Это придаёт смысл переменным в пределах этой функции и ссылку на родительское окружение. И это означает, что функции «запоминают» окружение или область видимости, так как они буквально ссылаются на это окружение. Это и есть замыкание.
- Замыкания создаются каждый раз при вызове внешней функции. Другими словами, внутренняя функция не будет возвращена для замыкания, в котором была создана.
- Область видимости замыканий в JavaScript лексическая, её смысл определяется статично в зависимости от нахождения в исходном коде.
- Есть множество практических случаев использования замыканий. Один из важных случаев использования — это сохранение приватных ссылок к переменным во внешней среде.
Замыкающая ремарка
Я надеюсь этот пост был полезным и дал представление о том, как замыкания реализованы в JavaScript. Как вы видите, понимание внутреннего устройства замыканий и особенностей их работы делают их поиск проще. Теперь у вас будет меньше головной боли при отладке.
Дополнительная литература
Для краткости я опустила несколько тем, которые могут быть интересны для некоторых читателей. Вот несколько ссылок, которыми я хотела бы поделиться:
Есть что-то ещё? Предлагайте.
JavaScript Объем
Область является набор переменных, которые имеют доступ.
JavaScript Область применения
В JavaScript объекты и функции также являются переменными.
В JavaScript, область является множество переменных, объектов и функций , которые имеют доступ.
JavaScript имеет область видимости функции: Масштаб изменений внутри функции.
Локальные переменные JavaScript
Переменные , объявленные внутри функции JavaScript, становятся локальными по отношению к функции.
Локальные переменные имеют локальную область видимости: они могут быть доступны только в пределах функции.
пример
// code here can not use carName
function myFunction() {
var carName = «Volvo»;
// code here can use carName
}
Попробуй сам »
Так как локальные переменные распознаются только внутри своих функций, переменные с одинаковыми именами могут быть использованы в различных функциях.
Локальные переменные создаются при запуске функции, и удаляется, когда функция завершена.
JavaScript Глобальные переменные
Переменная , объявленная вне функции, становится глобальным.
Глобальная переменная имеет глобальную область: Все скрипты и функции на веб — странице можно получить доступ к нему.
пример
var carName = » Volvo»;
// code here can use carName
function myFunction() {
// code here can use carName
}
Попробуй сам »
Автоматически Global
Если присвоить значение переменной , которая не была объявлена, она автоматически станетглобальной переменной.
В этом примере код будет объявить carName как глобальную переменную, даже если она выполняется внутри функции.
пример
// code here can use carName
function myFunction() {
carName = «Volvo»;
// code here can use carName
}
Попробуй сам »
НЕ создавать глобальные переменные, если вы не намерены.
В «строгий режим» автоматически глобальные переменные будут терпеть неудачу.
Время жизни переменных JavaScript
Время жизни переменной JavaScript начинается, когда она объявлена.
Локальные переменные удаляются, когда функция завершена.
Глобальные переменные удаляются при закрытии страницы.
Аргументы функции
Аргументы функции (параметры) работают как локальные переменные внутри функций.
Глобальные переменные в HTML
С помощью JavaScript, глобальный масштаб является полная среда JavaScript.
В HTML, глобальный масштаб является объектом окна: Все глобальные переменные относятся к объекту окна.
Вы знали?
Ваши глобальные переменные (или функции) могут перезаписать окна переменных (или функции).
Любая функция, в том числе объект окна, может перезаписать глобальные переменные и функции.
Области видимости и пространства имён
Хотя JavaScript нормально понимает синтаксис двух фигурных скобок, окружающих блок, он не поддерживает блочную область видимости; всё что остаётся на этот случай в языке — область видимости функций.
function test() {
// область видимости
for (var i = 0; i < 10; i++) {
// не область видимости
// считаем
}
console.log(i) // 10
}
Замечание: Нотация
{...}
будет интерпретирована как блочное выражение, а не как литерал объекта, если она не используется в присваивании, оператореreturn
или в качестве функции. Это замечание, вкупе с автоматической расстановкой точек с запятой, может привести к чрезвычайно хитрым ошибкам.
Также JavaScript не знает ничего о различиях в пространствах имён: всё определяется в глобально доступном пространстве имён.
Каждый раз, когда JavaScript обнаруживает ссылку на переменную, он будет искать её всё выше и выше по областям видимости, пока не найдёт её. В случае, если он достигнет глобальной области видимости и не найдет запрошенное имя и там тоже, он ругнётся ReferenceError
.
Проклятие глобальных переменных
// скрипт A
foo = '42'
// скрипт B
var foo = '42'
Вышеприведённые два скрипта не приводят к одному результату. Скрипт A определяет переменную по имени foo
в глобальной области видимости, а скрипт B определяет foo
в текущей области видимости.
Повторимся, это вообще не тот же самый эффект. Если вы не используете var
— то вы в большой опасности.
// глобальная область видимости
var foo = 42
function test() {
// локальная область видимости
foo = 21
}
test()
foo // 21
Из-за того что оператор var
опущен внутри функции, фунция test
перезапишет значение foo
. Это поначалу может показаться не такой уж и большой проблемой, но если у вас имеется тысяча строк JavaScript-кода и вы не используете var
, то вам на пути встретятся страшные и трудноотлаживаемые ошибки — и это не шутка.
// глобальная область видимости
var items = [
/* какой-то список */
]
for (var i = 0; i < 10; i++) {
subLoop()
}
function subLoop() {
// область видимости subLoop
for (i = 0; i < 10; i++) {
// пропущенный оператор var
// делаем волшебные вещи!
}
}
Внешний цикл прекратит работу сразу после первого вызова subLoop
, поскольку subLoop
перезаписывает глобальное значение переменной i
. Использование var
во втором цикле for
могло бы вас легко избавить от этой ошибки. Никогда не забывайте использовать var
, если только влияние на внешнюю область видимости не является тем, что вы намерены получить.
Локальные переменные
Единственный источник локальных переменных в JavaScript — это параметры функций и переменные, объявленные с использованием оператора var
.
// глобальная область видимости
var foo = 1
var bar = 2
var i = 2
function test(i) {
// локальная область видимости для функции test
i = 5
var foo = 3
bar = 4
}
test(10)
В то время как foo
и i
— локальные переменные в области видимости функции test
, присвоение bar
переопределит значение одноимённой глобальной переменной.
Всплытие
В JavaScript действует механизм всплытия определения. Это значит, что оба определения с использованием var
и определение function
будут перенесены наверх заключающей их области видимости.
bar()
var bar = function () {}
var someValue = 42
test()
function test(data) {
if (false) {
goo = 1
} else {
var goo = 2
}
for (var i = 0; i < 100; i++) {
var e = data[i]
}
}
Этот код трансформируется ещё перед исполнением. JavaScript перемещает операторы var
и определение function
наверх ближайшей оборачивающей области видимости.
// выражения с var переместились сюда
var bar, someValue // по умолчанию - 'undefined'
// определение функции тоже переместилось
function test(data) {
var goo, i, e // потерянная блочная область видимости
// переместилась сюда
if (false) {
goo = 1
} else {
goo = 2
}
for (i = 0; i < 100; i++) {
e = data[i]
}
}
bar() // вылетает с ошибкой TypeError,
// поскольку bar всё ещё 'undefined'
someValue = 42 // присвоения не подвержены всплытию
bar = function () {}
test()
Потерянная область видимости блока не только переместит операторы var
вовне циклов и их тел, но и сделает результаты некоторых конструкций с if
неинтуитивными.
В исходном коде оператор if
изменял глобальную переменную goo
, когда, как оказалось, он изменяет локальную переменную — в результате работы всплытия.
Если вы не знакомы со всплытием, то можете посчитать, что нижеприведённый код должен породить ReferenceError
.
// проверить, проинициализована ли SomeImportantThing
if (!SomeImportantThing) {
var SomeImportantThing = {}
}
Но, конечно же, этот код работает: из-за того, что оператор var
был перемещён наверх глобальной области видимости
var SomeImportantThing
// другой код может инициализировать здесь переменную SomeImportantThing,
// а может и нет
// убедиться, что она всё ещё здесь
if (!SomeImportantThing) {
SomeImportantThing = {}
}
Порядок разрешения имён
Все области видимости в JavaScript, включая глобальную области видимости, содержат специальную, определённую внутри них, переменную this
, которая ссылается на текущий объект.
Области видимости функций также содержат внутри себя переменную arguments
, которая содержит аргументы, переданные в функцию.
Например, когда JavaScript пытается получить доступ к переменной foo
в области видимости функции, он будет искать её по имени в такой последовательности:
- Если в текущей области видимости есть выражение
var foo
, использовать его. - Если один из параметров функции называется
foo
, использовать его. - Если функция сама называется
foo
, использовать её. - Перейти на одну область видимости выше и начать с п. 1
Замечание: Наличие параметра функции с именем
arguments
не позволит движку создать объектarguments
, создающийся по умолчанию.
Пространства имён
Нередкое последствие наличия только одного глобального пространства имён — проблема с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя анонимные обёртки.
;(function () {
// самостоятельно созданное "пространство имён"
window.foo = function () {
// открытое замыкание
}
})() // сразу же выполнить функцию
Безымянные функции являются выражениями; поэтому, чтобы вы имели возможность их выполнить, они сперва должны быть разобраны.
// разобрать функцию внутри скобок
;(function () {})() // и вернуть объект функции // вызвать результат разбора
Есть другие способы разбора и последующего вызова выражения с функцией; они, хоть и различаются в синтаксисе, но действуют одинаково.
// Два других способа
;+(function () {})()
;(function () {})()
Заключение
Рекомендуется всегда использовать анонимную обёртку для заключения кода в его собственное пространство имён. Это не только защищает код от совпадений имён, но и позволяет создавать более модульные программы.
Важно добавить, что использование глобальных переменных считается плохой практикой. Любое их использование демонстрирует плохое качество кода и может привести к трудноуловимым ошибкам.
получение доступа к элементам, глобальные и локальные переменные
- Главная
- ->
- Материалы
- ->
- JavaScript: получение доступа к элементам, глобальные и локальные переменные
Reg.ru: домены и хостинг
Крупнейший регистратор и хостинг-провайдер в России.
Более 2 миллионов доменных имен на обслуживании.
Продвижение, почта для домена, решения для бизнеса.
Более 700 тыс. клиентов по всему миру уже сделали свой выбор.
Перейти на сайт->
Бесплатный Курс «Практика HTML5 и CSS3»
Освойте бесплатно пошаговый видеокурс
по основам адаптивной верстки
на HTML5 и CSS3 с полного нуля.
Начать->
Фреймворк Bootstrap: быстрая адаптивная вёрстка
Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.
Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.
Верстайте на заказ и получайте деньги.
Получить в подарок->
Бесплатный курс «Сайт на WordPress»
Хотите освоить CMS WordPress?
Получите уроки по дизайну и верстке сайта на WordPress.
Научитесь работать с темами и нарезать макет.
Бесплатный видеокурс по рисованию дизайна сайта, его верстке и установке на CMS WordPress!
Получить в подарок->
*Наведите курсор мыши для приостановки прокрутки.
Назад
Вперед
JavaScript: получение доступа к элементам, глобальные и локальные переменные
Данный видеоурок является продолжением предыдущей части — Основы работы с переменными и функциями в JavaScript.
В этом уроке мы рассмотрим два основных вопроса:
1. Как получить доступ к элементам страницы с помощью JavaScript;
2. В чем разница между глобальными и локальными переменными.
Вы узнаете, какой метод используется в JavaScript для выбора элемента страницы по его идентификатору и научитесь применять его на практике.
Затем мы рассмотрим, какой метод позволяет получить значение, заключенное между html-тэгами какого-либо элемента. После этого Вы увидите, как можно выбрать элементы на странице по html-тэгам, а не по идентификаторам.
Здесь же Вы узнаете, каким образом можно получить доступ к какому-то конкретному элементу в случае, если заданному нами условию соответствует более одного объекта.
Также мы рассмотрим, как можно изменять значения, заключенные между тэгами, и придавать им стилевые параметры средствами JavaScript.
В заключительной части видеоурока мы поговорим об отличиях глобальных и локальных переменных в JavaScript.
Для ознакомления с содержанием урока Вы можете просмотреть видео ниже. Скачать видеоурок в высоком качестве можно по ссылке выше.
P.S. Присмотритесь к премиум-урокам по различным аспектам сайтостроения, включая JavaScript, jQuery и Ajax, а также к бесплатному курсу по созданию своей CMS-системы на PHP с нуля. Все это поможет вам быстрее и проще освоить практические навыки веб-программирования:
Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!
Смотрите также:
Наверх
Демистифицируем область действия переменных JavaScript и поднимаем их вверх
Сохранение значений в переменных — фундаментальная концепция в программировании. «Область действия» переменной определяет, когда она доступна, а когда нет в вашей программе. Понимание области видимости переменных в JavaScript — один из ключей к созданию прочной основы языка.
В этой статье объясняется, как работает система определения области видимости JavaScript. Вы узнаете о различных способах объявления переменных, различиях между локальной и глобальной областью видимости, а также о чем-то, называемом «подъем» — уловке JavaScript, которая может превратить невинно выглядящее объявление переменной в тонкую ошибку.
Диапазон изменения
В JavaScript область действия переменной контролируется местоположением объявления переменной и определяет часть программы, в которой доступна конкретная переменная.
В настоящее время существует трех способов объявления переменной в JavaScript: с помощью старого ключевого слова var
и с помощью нового ключевого слова let
и const
. До ES6 использование ключевого слова var
было единственным способом объявления переменной, но теперь мы можем использовать let
и const
, которые имеют более строгие правила и делают код менее подверженным ошибкам.Ниже мы рассмотрим различия между всеми тремя ключевыми словами.
Правила определения объема варьируются от языка к языку. JavaScript имеет две области : глобальную и локальную . Локальная область видимости имеет два варианта: старая область видимости функции и новая область видимости блока , представленная в ES6. Стоит отметить, что область видимости функции на самом деле является особым типом области видимости блока.
Global Scope
В сценарии самая внешняя область видимости — это глобальная область.Любые переменные, объявленные в этой области, становятся глобальными переменными и доступны из любой точки программы:
const name = "Моник";
function sayHi () {
console.log (`Привет, $ {name}`);
}
скажи привет();
Как показывает этот простой пример, переменная имя
является глобальной. Он определен в глобальной области видимости и доступен во всей программе.
Но как бы удобно это ни казалось, использование глобальных переменных в JavaScript не приветствуется. Это, например, связано с тем, что они потенциально могут быть перезаписаны другими сценариями или откуда-то еще в вашей программе.
Локальная область действия
Любые переменные, объявленные внутри блока, принадлежат этому конкретному блоку и становятся локальными переменными.
Функция в JavaScript определяет область для переменных, объявленных с использованием var
, let
и const
. Любая переменная, объявленная в этой функции, доступна только из этой функции и любых вложенных функций.
Кодовый блок (, если
, для
и т. Д.) Определяет область только для переменных, объявленных с ключевыми словами let
и const
.Ключевое слово var
ограничено областью действия функции, что означает, что новая область действия может быть создана только внутри функций.
Ключевые слова let
и const
имеют область видимости блока, которая создает новую локальную область видимости для любого блока, в котором они объявлены. Вы также можете определять отдельные блоки кода в JavaScript, и они аналогичным образом ограничивают область действия:
{
}
Области действия функций и блоков могут быть вложенными. В такой ситуации с несколькими вложенными областями видимости переменная доступна в пределах своей собственной области или из внутренней области.Но за пределами области действия переменная недоступна.
Простой пример, помогающий визуализировать область действия
Чтобы прояснить ситуацию, давайте воспользуемся простой метафорой. У каждой страны в нашем мире есть границы. Все, что находится внутри этих границ, относится к сфере действия страны. В каждой стране есть много городов, и каждый из них имеет свой городской масштаб. Страны и города подобны функциям или блокам JavaScript. У них свои локальные прицелы. То же самое и с континентами.Хотя они огромны по размеру, их также можно определить как локали.
С другой стороны, мировые океаны нельзя определить как имеющие локальную область действия, потому что они фактически охватывают все локальные объекты — континенты, страны и города — и, таким образом, их область действия определяется как глобальная. Давайте представим это в следующем примере:
var locales = {
европа: функция () {
var myFriend = "Моник";
var france = function () {
var paris = function () {
консоль.журнал (myFriend);
};
Париж();
};
Франция();
}
};
locales.europe ();
См. Pen
Variable Scope: 1 от SitePoint (@SitePoint)
на CodePen.
Здесь переменная myFriend
доступна из функции paris
, как она была определена во внешней области видимости функции france
. Если мы поменяем местами переменную myFriend
и оператор консоли, мы получим ReferenceError: myFriend не определен как
, потому что мы не можем достичь внутренней области из внешней области.
Теперь, когда мы понимаем, что такое локальные и глобальные области видимости и как они создаются, пора узнать, как интерпретатор JavaScript использует их для поиска конкретной переменной.
Возвращаясь к данной метафоре, допустим, я хочу найти своего друга по имени Моник. Я знаю, что она живет в Париже, поэтому и начинаю поиски оттуда. Когда я не могу найти ее в Париже, я поднимаюсь на один уровень выше и расширяю свой поиск по всей Франции. Но опять же, ее там нет. Затем я снова расширяю свой поиск, поднимаясь на другой уровень выше.Наконец, я нахожу ее в Италии, которая в нашем случае является локальным размахом Европы.
В предыдущем примере мой друг Моник представлен переменной myFriend
. В последней строке мы вызываем функцию europe ()
, которая вызывает france ()
, и, наконец, когда вызывается функция paris ()
, начинается поиск. Интерпретатор JavaScript работает в текущей области видимости и работает до тех пор, пока не найдет нужную переменную.Если переменная не найдена ни в одной области, создается исключение.
Этот тип поиска называется лексической (статической) областью видимости. Статическая структура программы определяет область действия переменной. Область действия переменной определяется ее местоположением в исходном коде, а вложенные функции имеют доступ к переменным, объявленным во внешней области. Независимо от того, откуда вызывается функция или даже как она вызывается, ее лексическая область видимости зависит только от того, где функция была объявлена.
Теперь посмотрим, как работает новая область видимости блока:
function testScope (n) {
если правда) {
константное приветствие = 'Привет';
пусть имя = п;
консоль.журнал (приветствие + "" + имя);
}
console.log (приветствие + "" + имя);
}
testScope ('Дэвид');
См. Pen
Variable Scope: 2 от SitePoint (@SitePoint)
на CodePen.
В этом примере мы видим, что приветствие
и называют переменные
, объявленные с const
и let,
недоступны за пределами блока if
.
Давайте теперь заменим const
и let
на var
и посмотрим, что получится:
function testScope (n) {
если правда) {
var приветствие = 'Привет';
var name = n;
консоль.журнал (приветствие + "" + имя);
}
console.log (приветствие + "" + имя);
}
testScope ('Дэвид');
См. Pen
Variable Scope: 3 от SitePoint (@SitePoint)
на CodePen.
Как видите, когда мы используем ключевое слово var
, переменные достижимы во всей области действия функции.
В JavaScript переменные с одинаковыми именами могут быть указаны на нескольких уровнях вложенной области видимости. В такой ситуации локальные переменные имеют приоритет над глобальными.Если вы объявляете локальную переменную и глобальную переменную с тем же именем, локальная переменная будет иметь приоритет, когда вы используете ее внутри функции или блока. Этот тип поведения называется затенение . Проще говоря, внутренняя переменная затеняет внешнюю.
Это точный механизм, используемый, когда интерпретатор JavaScript пытается найти определенную переменную. Он начинается с самой внутренней области, выполняемой в данный момент, и продолжается до тех пор, пока не будет найдено первое совпадение, независимо от того, есть ли другие переменные с тем же именем на внешних уровнях или нет.Давайте посмотрим на пример:
var test = «Я глобальный»;
function testScope () {
var test = "Я местный";
console.log (тест);
}
testScope ();
console.log (тест);
См. Pen
Variable Scope: 4 от SitePoint (@SitePoint)
на CodePen.
Даже с тем же именем локальная переменная не перезаписывает глобальную после выполнения функции testScope ()
. Но так бывает не всегда. Давайте посмотрим на это:
var test = «Я глобальный»;
function testScope () {
test = "Я местный";
консоль.журнал (тест);
}
console.log (тест);
testScope ();
console.log (тест);
См. Pen
Variable Scope: 5 от SitePoint (@SitePoint)
на CodePen.
На этот раз локальная переменная test
перезаписывает глобальную переменную с тем же именем. Когда мы запускаем код внутри функции testScope ()
, глобальная переменная переназначается. Если локальная переменная назначается без предварительного объявления с ключевым словом var
, она становится глобальной переменной.Чтобы избежать такого нежелательного поведения, вы всегда должны объявлять свои локальные переменные перед их использованием. Любая переменная, объявленная с ключевым словом var
внутри функции, является локальной переменной. Рекомендуется объявлять переменные.
Примечание. В строгом режиме будет ошибкой присвоить значение переменной без предварительного объявления переменной.
Подъемник
Интерпретатор JavaScript выполняет множество операций за кулисами, и одна из них — «подъем».Если вы не подозреваете об этом «скрытом» поведении, это может вызвать большую путаницу. Лучший способ думать о поведении переменных JavaScript — всегда визуализировать их как состоящие из двух частей: объявления и инициализации / присвоения:
состояние var;
состояние = "готово";
var state = "готово";
В приведенном выше коде мы сначала объявляем переменную state
, а затем присваиваем ей значение «готов»
. И в последней строке кода мы видим, что эти два шага можно комбинировать.Но что вам нужно иметь в виду, так это то, что, хотя они кажутся одним оператором, на практике движок JavaScript обрабатывает этот единственный оператор как два отдельных оператора, как в первых двух строках примера.
Мы уже знаем, что любая переменная, объявленная в области видимости, принадлежит этой области. Но чего мы пока не знаем, так это того, что независимо от того, где переменные объявлены в определенной области, все объявления переменных перемещаются в верхнюю часть своей области (глобальной или локальной).Это называется поднятием , так как объявления переменных поднимаются в верхнюю часть области видимости. Обратите внимание, что подъем перемещает только объявление. Любые назначения остаются на месте. Давайте посмотрим на пример:
console.log (состояние);
var state = "готово";
См. Pen
Variable Scope: 6 от SitePoint (@SitePoint)
на CodePen.
Как видите, когда мы регистрируем значение состояния
, на выходе получается undefined
, потому что мы ссылаемся на него до фактического присвоения.Вы могли ожидать, что будет выдано ReferenceError
, потому что состояние
еще не объявлено. Но вы не знаете, что переменная объявлена и инициализирована значением по умолчанию undefined
за сценой. Вот как код интерпретируется движком JavaScript:
состояние var;
console.log (состояние);
состояние = "готово";
Важно отметить, что переменная не перемещается физически.Подъем — это всего лишь модель, описывающая то, что движок JS делает за кулисами.
Теперь давайте посмотрим, как работает подъем с переменными let
:
{
console.log (состояние);
пусть состояние = "готово";
}
См. Pen
Variable Scope: 7 от SitePoint (@SitePoint)
на CodePen.
В этом примере вывод консоли — это не undefined
, но выдается справочная ошибка. Почему? Переменные let
, в отличие от переменных var
, не могут быть прочитаны / записаны, пока они не будут полностью инициализированы.Они полностью инициализируются только там, где они фактически объявлены в коде. Итак, объявление переменной let
поднимается, но не инициализируется значением undefined
, как в случае с переменными var
. Участок от начала блока до фактического объявления переменной называется временной мертвой зоной . Это механизм, который обеспечивает лучшую практику программирования, заставляя вас объявлять переменную перед ее использованием. Если мы переместим консольный оператор из TDZ, мы получим ожидаемый результат: ready
.
{
пусть состояние = "готово";
console.log (состояние);
}
См. Pen
Variable Scope: 8 от SitePoint (@SitePoint)
на CodePen.
Переменные, объявленные с ключевым словом const
, имеют то же поведение, что и переменные let
.
Функции
Подъем также влияет на объявления функций. Но прежде чем мы рассмотрим несколько примеров, давайте сначала узнаем разницу между объявлением функции и выражением функции:
функция showState () {}
var showState = function () {};
Самый простой способ отличить объявление функции от выражения функции — это проверить позицию слова функция
в операторе.Если функция
— это самое первое в инструкции, то это объявление функции. В противном случае это выражение функции.
Объявления функций полностью подняты. Это означает, что тело всей функции перемещается наверх. Это позволяет вызывать функцию до ее объявления:
showState ();
function showState () {
console.log («Готово»);
}
var showState = function () {
console.log («Ожидание»);
};
См. Pen
Variable Scope: 9 от SitePoint (@SitePoint)
на CodePen.
Причина, по которой предыдущий код работает, заключается в том, что механизм JavaScript перемещает объявление функции showState ()
и все ее содержимое в начало области. Код интерпретируется так:
function showState () {
console.log («Готово»);
}
var showState;
showState ();
showState = function () {
console.log («Ожидание»);
};
Как вы могли заметить, поднимается только объявление функции, а выражение функции — нет.Когда функция назначается переменной, правила те же, что и для подъема переменной (перемещается только объявление, а присваивание остается на месте).
В приведенном выше коде мы видели, что объявление функции имеет приоритет над объявлением переменной. А в следующем примере мы увидим, что когда у нас есть объявление функции, а не присвоение переменной, последнее имеет приоритет:
var showState = function () {
console.log («Ожидание»);
};
function showState () {
консоль.журнал («Готово»);
}
showState ();
См. Pen
Variable Scope: 10 от SitePoint (@SitePoint)
на CodePen.
На этот раз мы вызываем функцию showState ()
в последней строке кода, что меняет ситуацию. Теперь получаем на выходе "Idle"
. Вот как это выглядит при интерпретации движком JavaScript:
function showState () {
console.log («Готово»);
}
var showState;
showState = function () {
консоль.журнал ("Ожидание");
};
showState ();
Примечание: стрелочные функции работают идентично функциональным выражениям.
Классы
Объявления классов
также поднимаются аналогично переменным, объявленным с помощью оператора let
:
var user = new Person ('Дэвид', 33);
class Person {
конструктор (имя, возраст) {
this.name = name;
this.age = возраст;
}
}
См. Pen
Variable Scope: 11 от SitePoint (@SitePoint)
на CodePen.
В этом примере мы видим, что использование класса Person
перед объявлением вызывает ошибку ссылки, аналогичную той, что была в переменных let
. Чтобы исправить это, мы должны использовать класс Person
после объявления:
class Person {
конструктор (имя, возраст) {
this.name = name;
this.age = возраст;
}
}
var user = new Person ('Дэвид', 33);
console.log (пользователь);
См. Pen
Variable Scope: 12 от SitePoint (@SitePoint)
на CodePen.
Классы также могут быть созданы с использованием выражения класса, используя var
, let
или const
операторы объявления переменных:
console.log (typeof Person);
var user = new Person ('Дэвид', 33);
var Person = class {
конструктор (имя, возраст) {
this.name = name;
this.age = возраст;
}
};
См. Pen
Variable Scope: 13 от SitePoint (@SitePoint)
на CodePen.
В этом примере мы видим, что класс Person
поднимается как выражение функции, но его нельзя использовать, поскольку его значение — undefined
.Опять же, чтобы исправить это, мы должны использовать класс Person
после объявления:
console.log (typeof Person);
var Person = class {
конструктор (имя, возраст) {
this.name = name;
this.age = возраст;
}
};
var user = new Person ('Дэвид', 33);
console.log (пользователь);
См. Pen
Variable Scope: 14 от SitePoint (@SitePoint)
на CodePen.
Что следует помнить
-
var
переменные имеют область видимости функции. -
let переменные
иconst
имеют блочную область видимости (включая функции). - Все объявления — классы, функции и переменные — поднимаются в верхнюю часть содержащей их области до того, как будет выполнена какая-либо часть вашего кода.
- Сначала поднимаются функции, затем переменные.
- Объявления функций имеют приоритет над объявлениями переменных, но не над назначениями переменных.
Функция
— Каков объем переменных в JavaScript?
TLDR
JavaScript имеет лексические (также называемые статическими) область видимости и замыкания.Это означает, что вы можете определить область действия идентификатора, посмотрев на исходный код.
Четыре прицела:
- Глобальный — видим всем
- Функция — видна внутри функции (и ее подфункций и блоков)
- Блок — виден внутри блока (и его подблоков)
- Модуль — виден внутри модуля
Вне особых случаев глобальной и модульной области, переменные объявляются с использованием var
(область функции), let
(область блока) и const
(область блока).Большинство других форм объявления идентификаторов имеют область видимости блока в строгом режиме.
Обзор
Область действия — это область кодовой базы, в которой действует идентификатор.
Лексическая среда — это отображение между именами идентификаторов и значениями, связанными с ними.
Область видимости формируется из связанной вложенности лексических сред, причем каждый уровень вложения соответствует лексической среде контекста выполнения-предка.
Эти связанные лексические среды образуют «цепочку» области видимости.Разрешение идентификатора — это процесс поиска в этой цепочке соответствующего идентификатора.
Разрешение идентификатора происходит только в одном направлении: наружу. Таким образом, внешняя лексическая среда не может «видеть» внутреннюю лексическую среду.
Есть три важных фактора при выборе области идентификатора в JavaScript:
- Как был объявлен идентификатор
- Где был объявлен идентификатор
- В строгом или нестрогом режиме
Некоторые способы объявления идентификаторов:
-
var
,let
иconst
- Функциональные параметры
- Параметр блока захвата
- Объявления функций
- Выражения с именованными функциями
- Неявно определенные свойства глобального объекта (т.е., пропущено
var
в нестрогом режиме) -
импорт
выписки -
оценка
Некоторые идентификаторы местоположения могут быть объявлены:
- Глобальный контекст
- Функциональное тело
- Блок обыкновенный
- Вершина структуры управления (например, цикл, if, while и т. Д.)
- Корпус управляющей конструкции
- Модули
Стили декларации
вар
Идентификаторы, объявленные с использованием var
, имеют область действия , за исключением случаев, когда они объявляются непосредственно в глобальном контексте, и в этом случае они добавляются как свойства глобального объекта и имеют глобальную область действия.Существуют отдельные правила их использования в функциях eval
.
лет и констант
Идентификаторы, объявленные с использованием let
и const
, имеют область действия блока , за исключением случаев, когда они объявлены непосредственно в глобальном контексте, и в этом случае они имеют глобальную область.
Примечание: let
, const
и var
все подняты. Это означает, что их логическая позиция определения — это верхняя часть их охватывающей области (блока или функции).Однако переменные, объявленные с использованием let
и const
, не могут быть прочитаны или назначены до тех пор, пока управление не пройдет точку объявления в исходном коде. Промежуточный период известен как временная мертвая зона.
функция f () {
function g () {
console.log (x)
}
пусть x = 1
грамм()
}
f () // 1, потому что x поднимается, даже если объявлен с помощью `let`!
Имена параметров функций
Имена параметров функции привязаны к телу функции.Обратите внимание, что в этом есть небольшая сложность. Функции, объявленные как аргументы по умолчанию, закрывают список параметров, а не тело функции.
Объявление функций
Объявления функций имеют область видимости блока в строгом режиме и область действия функции в нестрогом режиме. Примечание. Нестрогий режим — это сложный набор новых правил, основанный на необычных исторических реализациях различных браузеров.
Выражения именованных функций
Выражения именованных функций ограничены самими собой (например,g., с целью рекурсии).
Неявно определенные свойства глобального объекта
В нестрогом режиме неявно определенные свойства глобального объекта имеют глобальную область видимости, потому что глобальный объект находится в верхней части цепочки областей видимости. В строгом режиме это запрещено.
оценка
В строках eval
переменные, объявленные с использованием var
, будут помещены в текущую область видимости или, если eval
используется косвенно, как свойства глобального объекта.
Примеры
Следующее вызовет ошибку ReferenceError, потому что имена x
, y
и z
не имеют значения вне функции f
.
функция f () {
var x = 1
пусть y = 1
const z = 1
}
console.log (typeof x) // не определено (потому что var имеет область видимости функции!)
console.log (typeof y) // не определено (потому что тело функции - это блок)
console.log (typeof z) // не определено (поскольку тело функции является блоком)
Следующее вызовет ReferenceError для y
и z
, но не для x
, поскольку видимость x
не ограничена блоком.Блоки, которые определяют тела структур управления, например для
, для
и для
, ведут себя аналогичным образом.
{
var x = 1
пусть y = 1
const z = 1
}
console.log (x) // 1
console.log (typeof y) // не определено, потому что у `y` есть область видимости блока
console.log (typeof z) // не определено, потому что у `z` есть область видимости блока
Далее x
видны вне цикла, потому что var
имеет область действия:
для (var x = 0; x <5; ++ x) {}
консоль.log (x) // 5 (обратите внимание, что это вне цикла!)
... из-за такого поведения вам нужно быть осторожным при закрытии переменных, объявленных с использованием var
in loops. Здесь объявлен только один экземпляр переменной x
, который логически находится вне цикла.
Следующее печатает 5
пять раз, а затем печатает 5
шестой раз для console.log
вне цикла:
для (var x = 0; x <5; ++ x) {
setTimeout (() => консоль.log (x)) // закрывается над `x`, который логически расположен в верхней части охватывающей области, над циклом
}
console.log (x) // примечание: видим вне цикла
Следующие распечатки undefined
, потому что x
имеет блочную область видимости. Обратные вызовы выполняются один за другим асинхронно. Новое поведение для переменных let
означает, что каждая анонимная функция закрывается над другой переменной с именем x
(в отличие от var
), и поэтому печатаются целые числа с 0
по 4
.:
для (пусть x = 0; x <5; ++ x) {
setTimeout (() => console.log (x)) // Объявления `let` повторно объявляются для каждой итерации, поэтому замыкания захватывают разные переменные
}
console.log (typeof x) // не определено
Следующее сообщение НЕ вызовет ошибку ReferenceError
, потому что видимость x
не ограничена блоком; однако он напечатает undefined
, потому что переменная не была инициализирована (из-за оператора if
).
if (false) {
var x = 1
}
console.log (x) // здесь x был объявлен, но не инициализирован
Переменная, объявленная в верхней части цикла для
с использованием let
, привязана к телу цикла:
для (пусть x = 0; x <10; ++ x) {}
console.log (typeof x) // не определено, потому что `x` имеет блочную область видимости
Следующее вызовет ошибку ReferenceError
, поскольку видимость x
ограничена блоком:
if (false) {
пусть x = 1
}
консоль.log (typeof x) // не определено, потому что `x` имеет блочную область видимости
Переменные, объявленные с использованием var
, let
или const
, привязаны к модулям:
// module1.js
var x = 0
функция экспорта f () {}
//module2.js
импортировать f из 'module1.js'
console.log (x) // выдает ошибку ReferenceError
Следующее будет объявлять свойство глобального объекта, потому что переменные, объявленные с использованием var
в глобальном контексте, добавляются как свойства к глобальному объекту:
var x = 1
консоль.log (window.hasOwnProperty ('x')) // правда
пусть
и const
в глобальном контексте не добавляют свойства к глобальному объекту, но все же имеют глобальную область действия:
пусть x = 1
console.log (window.hasOwnProperty ('x')) // ложь
Параметры функции можно считать объявленными в теле функции:
функция f (x) {}
console.log (typeof x) // не определено, потому что `x` привязан к функции
Параметры блока захвата привязаны к телу блока захвата:
попробуйте {} catch (e) {}
консоль.log (typeof e) // undefined, потому что `e` привязан к блоку catch
Выражения именованных функций ограничиваются только самим выражением:
(функция foo () {console.log (foo)}) ()
console.log (typeof foo) // undefined, потому что область `foo` ограничена собственным выражением
В нестрогом режиме неявно определенные свойства глобального объекта имеют глобальную область видимости. В строгом режиме вы получите ошибку.
x = 1 // неявно определенное свойство глобального объекта (без "var"!)
консоль.log (x) // 1
console.log (window.hasOwnProperty ('x')) // правда
В нестрогом режиме объявления функций имеют область действия. В строгом режиме у них есть блокировка.
'строгое использование'
{
функция foo () {}
}
console.log (typeof foo) // не определено, потому что `foo` имеет блочную область видимости
Как это работает под капотом
Область действия определяется как лексическая область кода, в которой действует идентификатор.
В JavaScript каждый объект-функция имеет скрытую ссылку [[Environment]]
, которая является ссылкой на лексическое окружение контекста выполнения (фрейм стека), в котором он был создан.
Когда вы вызываете функцию, вызывается скрытый метод [[Call]]
. Этот метод создает новый контекст выполнения и устанавливает связь между новым контекстом выполнения и лексической средой объекта функции. Это делается путем копирования значения [[Environment]]
объекта-функции во внешнее ссылочное поле лексической среды нового контекста выполнения.
Обратите внимание, что эта связь между новым контекстом выполнения и лексической средой объекта функции называется замыканием.
Таким образом, в JavaScript область видимости реализуется через лексические среды, связанные вместе в «цепочку» внешними ссылками. Эта цепочка лексических сред называется цепочкой областей видимости, и разрешение идентификатора происходит путем поиска по цепочке соответствующего идентификатора.
Узнать больше.
Разница между локальной и глобальной переменной
- Подробности
Что такое переменная?
Переменная - это имя, присвоенное области хранения, которой программа может управлять.Тип переменной определяет размер и структуру памяти переменной.
Он также определяет диапазон значений, которые необходимо сохранить в этой памяти, и характер операций, которые могут быть применены к этой переменной.
В этом руководстве вы узнаете
Объем переменных
Объем переменной - это просто время жизни переменной. Это блок кода, в котором переменная применима или активна. Например:
function foo () { var x; }
Вы объявляете переменную «x» внутри функции «foo."Область этой переменной остается внутри этой функции, ее нельзя использовать вне этой функции.
Есть три места, где переменные можно объявлять на языке программирования переменных:
- Внутри функции или блока: Локальные переменные
- Вне всех функций: глобальные переменные
- В определении параметров функции: формальные параметры
КЛЮЧЕВАЯ РАЗНИЦА
- Локальная переменная объявляется внутри функции, тогда как глобальная переменная объявляется вне функции.
- Локальные переменные создаются, когда функция начинает выполнение, и теряются, когда функция завершается, с другой стороны, глобальная переменная создается при запуске выполнения и теряется при завершении программы.
- Локальная переменная не обеспечивает совместное использование данных, тогда как глобальная переменная обеспечивает совместное использование данных.
- Локальные переменные хранятся в стеке, тогда как глобальные переменные хранятся в фиксированном месте, определенном компилятором.
- Передача параметров требуется для локальных переменных, тогда как для глобальной переменной это не обязательно.
Локальная переменная
Локальная переменная определяется как тип переменной, объявленной в блоке программирования или подпрограммах.Его можно использовать только внутри подпрограммы или блока кода, в котором он объявлен. Локальная переменная существует до тех пор, пока блок функции не будет выполняться. После этого он будет уничтожен автоматически.
Пример локальной переменной
public int add () { int a = 4; int b = 5; вернуть a + b; }
Здесь «a» и «b» - локальные переменные
Глобальная переменная
Глобальная переменная в программе - это переменная, определенная вне подпрограммы или функции.Он имеет глобальную область видимости, что означает, что он сохраняет свою ценность на протяжении всего жизненного цикла программы. Следовательно, к нему можно получить доступ во всей программе с помощью любой функции, определенной в программе, если она не затенена.
Пример:
int a = 4; int b = 5; public int add () { вернуть a + b; }
Здесь «a» и «b» - глобальные переменные.
Локальная переменная по сравнению с Глобальные переменные
Вот некоторые фундаментальные различия между локальными и глобальными переменными.
Параметр | Локальный | Глобальный |
---|---|---|
Область действия | Он объявлен внутри функции. | Он объявлен вне функции. |
Значение | Если оно не инициализировано, сохраняется значение мусора. | Если оно не инициализировано, по умолчанию сохраняется ноль. |
Время жизни | Создается, когда функция начинает выполнение, и теряется при завершении функции. | Он создается до начала глобального выполнения программы и теряется при завершении программы. |
Совместное использование данных | Совместное использование данных невозможно, поскольку к данным локальной переменной может получить доступ только одна функция. | Совместное использование данных возможно, поскольку несколько функций могут обращаться к одной и той же глобальной переменной. |
Параметры | Передача параметров требуется для локальных переменных для доступа к значению в другой функции | Передача параметров не требуется для глобальной переменной, поскольку она видна во всей программе |
Изменение значения переменной | Когда значение локальной переменной изменяется в одной функции, изменения не видны в другой функции. | Когда значение глобальной переменной изменяется в одной функции, изменения видны в остальной части программы. |
Доступ к | Доступ к локальным переменным можно получить с помощью операторов внутри функции, в которой они объявлены. | Вы можете получить доступ к глобальным переменным с помощью любого оператора программы. |
Память | Хранится в стеке, если не указано иное. | Он хранится в фиксированном месте, определенном компилятором. |
Преимущества использования глобальных переменных
- Вы можете получить доступ к глобальной переменной из всех функций или модулей в программе
- Вам нужно только объявить глобальную переменную однократно вне модулей.
- Он идеально подходит для хранения «констант», так как помогает сохранить согласованность.
- Глобальная переменная полезна, когда несколько функций обращаются к одним и тем же данным.
Преимущества использования локальных переменных
- Использование локальных переменных дает гарантию того, что значения переменных останутся неизменными во время выполнения задачи
- Если несколько задач изменят одну переменную, которая выполняется одновременно, результат может быть быть непредсказуемым.Но объявление его как локальной переменной решает эту проблему, поскольку каждая задача создает свой собственный экземпляр локальной переменной.
- Вы можете дать локальным переменным одно и то же имя в разных функциях, потому что они распознаются только функцией, в которой они объявлены.
- Локальные переменные удаляются, как только любая функция завершается, и освобождает пространство памяти, которое они занимают.
Недостатки использования глобальных переменных
- Слишком много переменных, объявленных как глобальные, остаются в памяти до завершения выполнения программы.Это может вызвать проблему нехватки памяти.
- Данные могут быть изменены любой функцией. Любой оператор, написанный в программе, может изменить значение глобальной переменной. Это может дать непредсказуемые результаты в многозадачных средах.
- Если глобальные переменные больше не поддерживаются из-за рефакторинга кода, вам нужно будет изменить все модули, в которых они вызываются.
Недостатки использования локальных переменных
- Процесс отладки локальной переменной довольно сложен.
- Общие данные, необходимые для многократной передачи, поскольку обмен данными между модулями невозможен.
- У них очень ограниченная сфера применения.
Что полезнее?
Локальная и глобальная переменные одинаково важны при написании программы на любом языке. Однако большое количество глобальных переменных может занимать огромную память. Нежелательное изменение глобальных переменных становится трудно идентифицировать. Поэтому рекомендуется избегать объявления нежелательных глобальных переменных.
Область действия переменной в JavaScript: объяснение и примеры
Локальные переменные JavaScript
Локальные переменные - это те, которые объявлены внутри функции JavaScript. Эти локальные переменные имеют область видимости функции , что делает их доступными только внутри функции и невидимыми вне функции.
Пример локальной переменной
// Строки кода здесь не могут получить доступ к переменной mammalName.
function animalName ()
{
var mammalName = '' дельфин '';
// Код здесь может получить доступ к переменной mammalName.
}
В приведенном выше примере переменная mammalName является локальной для функции animalName (). Только код внутри функции animalName () может получить доступ к mammalName. Переменная теряет свою область видимости вне функции. Таким образом, переменная имеет функцию или локальную область видимости. Локальные переменные всегда объявляются с ключевым словом var.
Локальная переменная создается при запуске функции JavaScript и удаляется в конце функции.
Глобальные переменные JavaScript
Переменные, объявленные вне функции JavaScript, имеют глобальную область видимости и называются глобальными переменными .Все функции и скрипты в этом приложении (т. Е. Веб-странице) имеют доступ к глобальным переменным.
Пример глобальной переменной 1
var mammalName = '' Dolphin '';
// написанный здесь код JavaScript может получить доступ к переменной mammalName
function animalName ()
{
// код JavaScript здесь также может получить доступ к переменной mammalName
}
В приведенном выше примере переменная mammalName объявлена вне Функция JavaScript animalName ().Следовательно, его охват глобален.
Если переменная не объявлена с использованием ключевого слова var, значение, присвоенное этой переменной, становится глобальным, как показано в следующем примере.
Пример глобальной переменной 2
// Код JavaScript здесь может использовать имя млекопитающего
function animalName ()
{
mammalName = '' Dolphin '';
// Код JavaScript здесь может использовать имя млекопитающего
}
В приведенном выше примере переменная mammalName не объявлена как var mammalName.Таким образом, в этом коде область видимости этой переменной становится глобальной.
Приоритет переменной
Если локальная переменная и глобальная переменная объявлены с одним и тем же именем, наивысший приоритет отдается локальной переменной при доступе к переменной внутри функции (локальная область видимости), как показано ниже.
var name = '' Мэри '';
// Когда к имени переменной здесь обращаются с помощью кода, значение равно «Мэри»
function user ()
{
var name = '' Rose '';
// Когда здесь осуществляется доступ к имени переменной, оно принимает значение «Rose»
}
В приведенном выше примере, когда объявляются две переменные с одинаковым именем, локальная переменная имеет наивысший приоритет внутри области действия функции.Вне области действия функции приоритет имеет глобальная переменная.
Использование глобальных переменных
Глобальные переменные не должны использоваться в JavaScript. В JavaScript все части кода используют общее глобальное пространство имен, то есть каждый файл JavaScript на веб-странице выполняется в одной области. Если вы используете глобальную переменную в своем коде JavaScript, переменные с одинаковыми именами в коде будут перезаписывать значения друг друга.
Время жизни переменной
Жизненный цикл переменной JavaScript начинается после объявления переменной.Срок действия или видимость локальной переменной ограничивается функцией, в которой она объявлена. Он удаляется после завершения выполнения функции. Жизненный цикл глобальной переменной существует во всей программе JavaScript.
Сводка урока
Переменные JavaScript бывают двух типов областей действия:
Локальные переменные являются областями действия и видны только в той функции, в которой они объявлены. Глобальные переменные , с другой стороны, имеют глобальную область видимости и доступны для всех других функций или сценариев в программе JavaScript (т.е.е. веб-страницу). Не рекомендуется использовать глобальные переменные без крайней необходимости из-за проблем с перезаписью одноименных переменных.
Что такое локальные переменные в JavaScript?
При использовании JavaScript , локальные переменные - это переменные , которые определены в функциях. Они имеют локальную область действия , что означает, что они могут использоваться только в рамках функций, которые их определяют. Глобальная переменная : Напротив, глобальные переменные - это переменные , которые определены вне функций.
Щелкните, чтобы увидеть полный ответ.
Также нужно знать, что такое переменные JavaScript?
Переменная JavaScript - это просто имя места хранения. В JavaScript есть два типа переменных : локальная переменная и глобальная переменная . Есть некоторые правила при объявлении переменной JavaScript (также известной как идентификаторы). Имя должно начинаться с буквы (от a до z или от A до Z), подчеркивания (_) или знака доллара ($).
Аналогично, что такое $ scope в JavaScript? Область видимости в JavaScript относится к текущему контексту кода, который определяет доступность переменных для JavaScript . Два типа области - локальные и глобальные: глобальные переменные - это переменные, объявленные вне блока. Локальные переменные объявлены внутри блока.
Точно так же можно спросить, в чем разница между локальными и глобальными переменными в JavaScript?
Переменные JavaScript имеют только две области. Глобальные переменные - Глобальная переменная имеет глобальную область , что означает, что она может быть определена в любом месте кода JavaScript . Локальные переменные - Локальная переменная будет видна только внутри функции, в которой она определена. Параметрами функции всегда являются локальные для этой функции.
Как объявить переменную в JavaScript?
JavaScript использует зарезервированное ключевое слово var для объявления переменной .Переменная должна иметь уникальное имя. Вы можете присвоить значение переменной с помощью оператора равенства (=) при его объявлении или перед его использованием. В приведенном выше примере мы объявили три переменных с использованием ключевого слова var : one, two и three.
Область ужасов - глобальная, локальная и блочная область видимости в JS
В программировании объем переменной определяет ее время жизни . Область действия описывает, доступны или недоступны переменная, функция или объект для различных частей программы во время выполнения.В этой статье мы увидим примеры, кратко описывающие глобальную, локальную и блочную области видимости в JavaScript.
Ват это блоки?
Прежде чем углубляться в категории областей видимости, существующие в JS, мы должны сначала определить, что такое блок. Блок - это фрагмент кода внутри фигурных скобок {}, который объединяет операторы кода вместе. Примером блока может быть функция, например:
Глобальный охват
Переменная существует внутри или вне блока.Если переменная объявлена вне всех функций или фигурных скобок ({}), она существует в глобальной области . К глобальным переменным может обращаться любая строка кода в программе, включая внутренние блоки.
Местный охват
В отличие от глобальных переменных, переменные с локальной областью видимости видны только в той функции, в которой они объявлены. Каждая функция, написанная на JavaScript, создает новую локальную область видимости, и каждая переменная, объявленная в этой области видимости, является локальной переменной.Это означает, что переменные с одинаковыми именами могут использоваться в разных функциях. Однако любая попытка ссылаться на локальную переменную за пределами ее области приведет к ошибке ссылки:
Объем блока
До сих пор мы видели переменные, определенные с помощью ключевого слова var. Var может объявлять переменную либо в глобальной, либо в локальной области. Переменные, объявленные в области видимости блока, сопоставимы с локальными. Они доступны внутри блока, в котором они определены.
Основное различие между локальной областью видимости и областью действия блока состоит в том, что операторы блока (например, условия if или циклы) не создают новую область видимости. Таким образом, ключевое слово var не будет иметь эффекта, потому что переменные все еще находятся в той же области.
ES6 представил область видимости блока с помощью ключевых слов let и const. Эти два ключевых слова ограничены определенным блоком.
Зачем нужен объем?
Итак, зачем нужны области видимости и ограничивать видимость переменных? Во-первых, соображения безопасности.Переменные доступны только тогда, когда они необходимы. Во-вторых, область видимости решает проблему коллизии пространств имен, которая возникает, когда существуют переменные с тем же именем, но с разными областями действия. Наконец, это сэкономит память в вашем коде, потому что переменные блока перестанут существовать после того, как блок завершит работу.
Итого
-> Глобальные переменные действуют, пока работает приложение.
-> Локальные переменные действуют, пока функция работает.
-> Операторы блока не создают новую область видимости, и область действия блока не применяется к ключевому слову var.
-> Const и Let могут определять область действия блокирующих операторов.
Артикулы:
Понимание области действия в JS
JavaScript: базовое руководство по Scope
Область действия в Javascript
Понимание переменных, области действия и подъема в JavaScript
Область видимости и закрытия JavaScript
Область видимости и закрытия JavaScript | CSS-уловки
Области видимости и замыкания важны в JavaScript.Но они сбивали меня с толку, когда я только начинал. Вот объяснение областей действия и замыканий, которые помогут вам понять, что они из себя представляют.
Начнем с прицелов.
Область применения
Область видимости в JavaScript определяет, к каким переменным у вас есть доступ. Есть два вида областей видимости - глобальная и локальная.
Глобальный охват
Если переменная объявлена вне всех функций или фигурных скобок ( {}
), говорят, что она определена в глобальной области .
Это верно только для JavaScript в веб-браузерах. Вы объявляете глобальные переменные в Node.js по-другому, но мы не будем углубляться в Node.js в этой статье.
const globalVariable = 'какое-то значение'
После того, как вы объявили глобальную переменную, вы можете использовать эту переменную в любом месте вашего кода, даже в функциях.
const hello = 'Привет, читатель CSS-трюков!'
function sayHello () {
console.log (привет)
}
console.log (hello) // 'Привет, читатель CSS-трюков!'
sayHello () // 'Hello CSS-Tricks Reader!'
Хотя вы можете объявлять переменные в глобальной области видимости, не рекомендуется этого делать.Это связано с тем, что существует вероятность коллизии имен, когда две или более переменных называются одинаково. Если вы объявили свои переменные с const
или let
, вы получите сообщение об ошибке всякий раз, когда произойдет конфликт имен. Это нежелательно.
// Не делай этого!
пусть вещь = 'что-то'
let thing = 'something else' // Ошибка, вещь уже объявлена
Если вы объявляете свои переменные с помощью var
, ваша вторая переменная перезаписывает первую после того, как она была объявлена.Это также нежелательно, поскольку вы затрудняете отладку кода.
// Не делай этого!
var thing = 'что-то'
var thing = 'something else' // возможно где-то совсем другое в вашем коде
console.log (вещь) // 'что-то еще'
Итак, вы всегда должны объявлять локальные переменные, а не глобальные.
Локальная область действия
Переменные, которые можно использовать только в определенной части вашего кода, считаются находящимися в локальной области. Эти переменные также называются локальными переменными .
В JavaScript существует два вида локальной области видимости: область видимости функции и область видимости блока.
Давайте сначала поговорим об объемах функций.
Объем функций
Когда вы объявляете переменную в функции, вы можете получить доступ к этой переменной только внутри функции. Вы не сможете получить эту переменную, если выберетесь из нее.
В приведенном ниже примере переменная hello
находится в области sayHello
:
function sayHello () {
const hello = 'Привет, читатель CSS-трюков!'
консоль.журнал (привет)
}
sayHello () // 'Hello CSS-Tricks Reader!'
console.log (hello) // Ошибка, hello не определено
Объем блока
Когда вы объявляете переменную с const
или let
в фигурной скобке ( {}
), вы можете получить доступ к этой переменной только внутри фигурной скобки.
В приведенном ниже примере вы можете видеть, что hello
ограничено фигурной скобкой:
{
const hello = 'Привет, читатель CSS-трюков!'
консоль.log (hello) // 'Привет, читатель CSS-трюков!'
}
console.log (hello) // Ошибка, hello не определено
Область видимости блока - это подмножество области видимости функции, поскольку функции необходимо объявлять с помощью фигурных скобок (если вы не используете стрелочные функции с неявным возвратом).
Функциональные подъемники и опоры
Функции, объявленные с помощью объявления функции, всегда поднимаются наверх текущей области видимости. Итак, эти два эквивалента:
// Это то же самое, что и ниже
скажи привет()
function sayHello () {
консоль.log ('Привет, читатель CSS-трюков!')
}
// Это то же самое, что и код выше
function sayHello () {
console.log ('Привет, читатель CSS-трюков!')
}
SayHello ()
При объявлении с выражением функции функции не поднимаются в верхнюю часть текущей области видимости.
sayHello () // Ошибка sayHello не определена
const sayHello = function () {
console.log (функция)
}
Из-за этих двух вариантов подъем функций потенциально может сбивать с толку, и его не следует использовать.Всегда объявляйте свои функции перед их использованием.
Функции не имеют доступа к областям действия друг друга
Функции не имеют доступа к областям действия друг друга, если вы определяете их по отдельности, даже если одна функция может использоваться в другой.
В этом примере ниже второй
не имеет доступа к firstFunctionVariable
.
function first () {
const firstFunctionVariable = `Я часть первого`
}
function second () {
первый()
консоль.log (firstFunctionVariable) // Ошибка, firstFunctionVariable не определена
}
Вложенные области видимости
Когда функция определена в другой функции, внутренняя функция имеет доступ к переменным внешней функции. Такое поведение называется лексической областью видимости .
Однако внешняя функция не имеет доступа к переменным внутренней функции.
function outerFunction () {
const external = `Я внешняя функция!`
function innerFunction () {
const inner = `Я внутренняя функция!`
консоль.log (external) // Я внешняя функция!
}
console.log (inner) // Ошибка, inner не определен
}
Чтобы наглядно представить, как работают оптические прицелы, вы можете представить одностороннее стекло. Вы можете видеть снаружи, но люди снаружи вас не видят.
Области видимости в функциях ведут себя как одностороннее стекло. Вы можете видеть снаружи, но люди снаружи вас не видят
Если у вас есть прицелы внутри прицелов, визуализируйте несколько слоев одностороннего стекла.
Несколько уровней функций означают несколько слоев одностороннего стекла.
После того, как вы до сих пор понимаете все, что касается осциллографов, вы начинаете понимать, что такое замыкания.
Крышки
Каждый раз, когда вы создаете функцию внутри другой функции, вы создаете замыкание. Внутренняя функция - закрытие. Это закрытие обычно возвращается, чтобы вы могли использовать переменные внешней функции позже.
function outerFunction () {
const external = `Я вижу внешнюю переменную!`
function innerFunction () {
console.log (внешний)
}
вернуть innerFunction
}
externalFunction () () // Я вижу внешнюю переменную!
Поскольку возвращается внутренняя функция, вы также можете немного сократить код, написав оператор return при объявлении функции.
function outerFunction () {
const external = `Я вижу внешнюю переменную!`
return function innerFunction () {
console.log (внешний)
}
}
externalFunction () () // Я вижу внешнюю переменную!
Поскольку замыкания имеют доступ к переменным во внешней функции, они обычно используются для двух целей:
- Для контроля побочных эффектов
- Для создания частных переменных
Контроль побочных эффектов с помощью укупорочных средств
Побочные эффекты возникают, когда вы делаете что-то помимо возврата значения из функции.Многие вещи могут быть побочными эффектами, например, запрос Ajax, тайм-аут или даже заявление console.log
:
function (x) {
console.log ('console.log - это побочный эффект!')
}
Когда вы используете замыкания для управления побочными эффектами, вас обычно беспокоят те, которые могут испортить поток кода, такие как Ajax или тайм-ауты.
Давайте рассмотрим это на примере, чтобы прояснить ситуацию.
Допустим, вы хотите сделать торт на день рождения друга.На приготовление этого торта уйдет секунда, поэтому вы написали функцию, которая из журналов делает торт
через одну секунду.
Я использую здесь стрелочные функции ES6, чтобы сделать пример короче и проще для понимания.
function makeCake () {
setTimeout (_ => console.log (`Сделал торт`), 1000)
}
Как видите, у этой функции приготовления торта есть побочный эффект: тайм-аут.
Допустим, вы хотите, чтобы ваш друг выбрал аромат для торта.Для этого вы можете написать «добавить вкус» к вашей функции makeCake .
function makeCake (аромат) {
setTimeout (_ => console.log (`Сделал $ {ароматный} торт!`), 1000)
}
Когда вы запускаете функцию, обратите внимание, что торт готовится сразу через одну секунду.
makeCake ('банан')
// Сделал банановый торт!
Проблема в том, что вы не хотите готовить торт сразу после того, как узнаете его вкус. Вы хотите сделать это позже, когда придет время.
Чтобы решить эту проблему, вы можете написать функцию prepareCake
, которая сохраняет ваш вкус. Затем верните крышку makeCake
в prepareCake
.
С этого момента вы можете вызывать возвращаемую функцию, когда захотите, и торт будет приготовлен в течение секунды.
function prepareCake (ароматизатор) {
return function () {
setTimeout (_ => console.log (`Сделал $ {ароматный} торт!`), 1000)
}
}
const makeCakeLater = prepareCake ('банан')
// И позже в вашем коде...
makeCakeLater ()
// Сделал банановый торт!
Вот как закрытие используется для уменьшения побочных эффектов - вы создаете функцию, которая активирует внутреннее закрытие по вашей прихоти.
Частные переменные с замыканиями
Как вы уже знаете, к переменным, созданным в функции, нельзя получить доступ вне функции. Поскольку к ним нельзя получить доступ, они также называются частными переменными.
Однако иногда вам нужно получить доступ к такой частной переменной. Сделать это можно с помощью закрытий.
function secret (secretCode) {
возвращение {
saySecretCode () {
console.log (secretCode)
}
}
}
const theSecret = secret ('Уловки CSS потрясающие')
theSecret.saySecretCode ()
// "Уловки CSS просто потрясающие"
saySecretCode
в этом примере выше - единственная функция (закрытие), которая предоставляет секретный код
вне исходной секретной функции. Таким образом, она также называется привилегированной функцией .
Объемы отладки с помощью DevTools
Chrome и инструменты разработчика Firefox упрощают отладку переменных, к которым вы можете получить доступ в текущей области. Есть два способа использовать эту функцию.
Первый способ - добавить в код отладчика ключевое слово
. Это приводит к приостановке выполнения JavaScript в браузерах, чтобы вы могли отлаживать.
Вот пример с prepareCake
:
function prepareCake (ароматизатор) {
// Добавляем отладчик
отладчик
return function () {
setTimeout (_ => console.log (`Сделал торт за $ {аромат}!`), 1000)
}
}
const makeCakeLater = prepareCake ('банан')
Если вы откроете DevTools и перейдете на вкладку «Источники» в Chrome (или вкладку «Отладчик» в Firefox), вы увидите доступные вам переменные.
Отладка области действия prepareCake
Вы также можете переместить ключевое слово debugger
в закрытие. Обратите внимание, как на этот раз изменяются переменные области видимости:
function prepareCake (ароматизатор) {
return function () {
// Добавляем отладчик
отладчик
setTimeout (_ => console.log (`Сделал торт за $ {аромат}!`), 1000)
}
}
const makeCakeLater = prepareCake ('банан')
Отладка области закрытия
Второй способ использования этой функции отладки - это добавить точку останова в ваш код непосредственно на вкладке источников (или отладчика), щелкнув номер строки.
Объемы отладки путем добавления точек останова
Завершение
Области действия и закрытия не так уж и сложно понять. Они становятся довольно простыми, если вы знаете, как увидеть их через одностороннее стекло.
Когда вы объявляете переменную в функции, вы можете получить к ней доступ только в функции. Говорят, что эти переменные относятся к функции.
Если вы определяете какую-либо внутреннюю функцию внутри другой функции, эта внутренняя функция называется замыканием.