- Область видимости в Javascript
- Локальные переменные JavaScript
- Глобальные переменные JavaScript
- Автоматическая глобальная область видимости
- «Строгий» режим
- Глобальные переменные в HTML
- Предупреждение
- Жизненный цикл переменных JavaScript
- Аргументы функций
- Локальные и глобальные переменные в JavaScript
- Локальные переменные
- Жизненный цикл переменных
- Жизненный цикл переменной a
- Жизненный цикл переменной b
- Основные правила работы с переменными
- Область видимости переменной в Javascript (ликбез)
- Объявление переменных
- Наследование области видимости
- this
Область видимости в Javascript
Область видимости определяет доступность (видимость) переменных.
В JavaScript существует два типа области видимости:
При этом каждая функция JavaScript создает новую область видимости, которая определяет видимость переменных функции. Переменные, созданные внутри функции, не доступны за пределами этой функции.
Локальные переменные JavaScript
Переменные, декларированные внутри JavaScript функции, становятся ЛОКАЛЬНЫМИ по отношению к этой функции.
У локальных переменных локальная область видимости: получить доступ к ним можно только внутри конкретной функции.
// расположенный здесь код не может использовать переменную carName function myFunction() < var carName = "Volvo"; // расположенный здесь код может использовать переменную carName >
Так как локальные переменные доступны только внутри своих функций, в разных функциях допустимо использовать переменные с одинаковыми именами.
Локальные переменные создаются, когда функция начинает работать, и удаляются, когда работа функции заканчивается.
Глобальные переменные JavaScript
Переменные, декларированные за пределами JavaScript функций, становятся ГЛОБАЛЬНЫМИ.
У глобальных переменных глобальная область видимости: все скрипты и функции на данной веб-странице могут получить к ним доступ.
var carName = " Volvo"; // расположенный здесь код может использовать переменную carName function myFunction() < // расположенный здесь код может использовать переменную carName >
Внимание! В JavaScript объекты и функции также являются переменными.
Область видимости определяет доступность переменных, объектов и функций из различных частей кода.
Автоматическая глобальная область видимости
Если вы присваиваете значение переменной, которая ранее не была декларирована, то эта переменная автоматически становится глобальной.
В следующем примере декларируется глобальная переменная carName, хотя значение ей присваивается внутри функции:
myFunction(); // расположенный здесь код может использовать переменную carName function myFunction()
«Строгий» режим
Все современные браузеры поддерживают работу JavaScript в, так называемом, «строгом режиме».
В следующих главах данного учебника будет подробнее рассказано о том, что такое «строгий режим» и как его использовать.
В «строгом режиме» глобальные переменные не создаются автоматически.
Глобальные переменные в HTML
Для JavaScript глобальной областью видимости является все окружение JavaScript.
В HTML глобальная область видимости это окно браузера (объект window). Все глобальные переменные принадлежат объекту window.
var carName = "Volvo"; // расположенный здесь код может для доступа к переменной carName // может использовать выражение window.carName
Предупреждение
Не создавайте глобальные переменные, если в этом нет жесткой необходимости.
Ваши глобальные переменные (или функции) могут переписывать переменные (или функции) глобального объекта window. В свою очередь любая функция, включая объект window, может переписывать ваши глобальные переменные и функции.
Жизненный цикл переменных JavaScript
Жизненный цикл переменной JavaScript начинается во время ее декларирования.
Локальные переменные удаляются, когда функция, внутри которой они были декларированы, заканчивает свою работу.
Глобальные переменные в браузере прекращают свое существование, когда вы закрываете окно браузера (или вкладку страницы), однако они остаются доступными, если в то же окно загружается новая веб-страница.
Аргументы функций
Аргументы (параметры) функции работают как локальные переменные внутри функции.
Локальные и глобальные переменные в JavaScript
Глобальные переменные – это такие, которые объявлены в глобальной области видимости. То есть вне блока, функции и модуля.
// глобальная переменная сar let car = 'Audi';
Глобальная переменная доступна в любой части кода, только если она не пересекается с локальной переменной.
Доступ к глобальной переменной year внутри myFunc() :
// глобальные переменные car и year let car = 'Audi'; let year = 2007; function myFunc() { // локальная переменная car let car = 'Ford'; console.log(car); // "Ford" console.log(year); // 2007 } myFunc(); // "Audi"
Внутри функции myFunc() мы не сможем получить доступ к глобальной переменной car после объявления переменной с таким же именем внутри этой функции.
// глобальная переменная numberUsers let numberUsers = 0; // объявление функции addUsers const addUsers = (num) => { numberUsers += num; return numberUsers; } console.log(addUsers(5)); // 5 console.log(addUsers(2)); // 7 console.log(numberUsers); // 7
В это примере мы нарушили одно из ключевых правил: поменяли внутри функции значение внешней переменной. Это делать крайне не рекомендуется.
Локальные переменные
Локальные переменные – это такие, которые объявлены в локальной области видимости. Например, внутри блока {. } :
{ // количество просмотров let totalViews = 10; }
Локальные переменные имеют локальную область действия, т.е. они не будут доступны за пределами той области, в которой объявлены:
{ // количество просмотров let totalViews = 10; } console.log(totalViews); // Uncaught ReferenceError: totalViews is not defined
Локальные переменные с одними и теми же именами могут использоваться в разных блоках:
if (true) { let pageTitle = 'Учебник по JavaScript'; console.log(pageTitle); // "Учебник по JavaScript" } if (!false) { let pageTitle = 'Учебник по CSS'; console.log(pageTitle); // "Учебник по CSS" }
Локальные переменные доступны в других локальных областях видимости, созданных внутри этой:
if (true) { // количество просмотров let totalViews = 10; let addViews = () => { totalViews++; return totalViews; } if (totalViews) { addViews(); console.log(totalViews); // 11 } }
Жизненный цикл переменных
Рассмотрим жизненный цикл переменных a и b на следующем примере:
let a = 7; let b; const someFunc = () => { let b; a = null; b = 5; console.log(b); } someFunc(); console.log(a); console.log(b);
В этом примере мы объявили переменным a , b и someFunc в глобальной области видимости. Следовательно, эти переменные являются глобальными.
Переменной someFunc мы присвоили функциональное выражение. Далее мы вызвали эту функцию, используя данную переменную.
При вызове функции someFunc() создастся локальная область видимости функции. В этой области видимости мы объявили переменную b . Следовательно, эта переменная локальная.
При этом новая локальная область будет создаваться каждый при вызове someFunc() .
Жизненный цикл переменной a
1. Сначала переменная a объявляется в глобальной области видимости и ей сразу же с помощью оператора = присваивается число 7.
2. Вызов someFunc() создаёт локальную область видимости функции, которая содержит ссылку на глобальную область видимости. Здесь мы пытаемся присвоить переменной a значение null . Т.к. a в этой области нет, то мы переходим по ссылке к внешней области видимости, которая в данном случае является глобальной, и ищем переменную здесь. Здесь мы её находим и присваиваем ей новое значение, т.е. null .
Таким образом после выполнения этой строчки глобальная переменная a будет иметь значение null . Т.е. мы поменяли значение внешней переменной внутри функции.
3. После выполнения функции someFunc она возвращает значение undefined . Все локальные переменные, которые были созданы внутри неё больше не доступны и сборщик мусора их удаляет.
На следующем шаге, когда мы пытаемся вывести значение переменной a в консоль, интерпретатор находит её в текущей области видимости, которая является глобальной. При этом значение переменной уже не 7 , а null . Значение a мы изменили внутри функции.
Жизненный цикл переменной b
1. Переменная с именем b создаётся в глобальной области видимости. На этом шаге её значение undefined , т.к. ей не было присвоено значение.
2. При вызове функции someFunc() создаётся локальная область. В ней объявляется переменная b посредством let .
3. Затем на строке b = 5 хотим присвоить переменной b число 5 . Но сначала необходимо найти переменную b . Поиск переменной всегда начинается с текущей области видимости. В ней она есть. Следовательно берем её и присваиваем ей значение 5 . Т.е. мы присвоили значение локальной переменной, не глобальной.
4. На следующем шаге ( console.log(b) ) мы хотим вывести значение переменной b в консоль. Для того чтобы это сделать, нам нужно снова найти эту переменную. В данном случае мы её находим в области видимости функции и у этой переменной значение 5, которое мы ей присвоили ей на строке b = 5 . Следовательно, в консоль выведется значение 5 .
После этого функция someFunc() завершает свою работу. Она возвращает undefined . Но этот результат мы не кому не присваиваем и никуда не выводим.
5. Печатаем в консоль значение переменной b . Но чтобы это сделать нужно найти эту переменную. Сейчас мы находимся в глобальной области видимости и поэтому поиск нужно начинать отсюда. Здесь эта переменная имеет значение undefined , поэтому мы и увидим его в консоли.
Основные правила работы с переменными
Основные моменты, которые необходимо знать при работе с переменными в JavaScript:
- Включение строгого режима запрещает автоматическое создание не объявленных переменных;
- Переменные необходимо объявлять перед тем как их использовать;
- Создавать переменные необходимо посредством const там где это возможно. А let использовать для объявления только тех переменных, которым вы планируете потом присваивать новые значения;
- Объявлять переменные в глобальной области видимости крайне не желательно, количество таких переменных рекомендуется свести к минимуму;
- Функции стараться писать так, чтобы они не изменяли внешние переменные.
Область видимости переменной в Javascript (ликбез)
Переменные в Javascript бывают глобальными и локальными. Глобальная переменная доступна везде, локальная — только в текущей области видимости.
Технически, глобальные переменные — всего лишь свойства объекта window , поскольку весь код выполняется в его контексте.
Из этого следует, что глобальные переменные могут затирать свойства window (я уже молчу о том, что они зло, нарушают инкапсуляцию и все такое).
Объявление переменных
При присвоении значения неопределенной локальной переменной используется или создается глобальная переменная.
function foo() < a = 2; b = 3; return a+b; >alert(a); // undefined a = 'очень важное значение'; alert(a); // очень важное значение foo(); alert(a); // 2
Таким образом можно легко затереть лишнего. По-моему такое поведение абсолютно нелогично, но, что ж, это не самое странное место яваскрипта. В любом случае неявного определения переменных стоит избегать.
Явно объявлять переменные можно и нужно ключевым словом var .
Такая строка всегда создает новую локальную переменную. Если объявление происходит вне функций, то она будет глобальной, что вполне логично.
function foo() < var a = 2; var b = 3; return a+b; >alert(a); // undefined var a = 'очень важное значение'; alert(a); // очень важное значение foo(); alert(a); // очень важное значение
Как объявить глобальную переменную из функции? Как обратиться к глобальной переменной, если есть локальная с таким же именем? Очень просто — нужно обратиться к ней как к свойству window :
function foo() < var location = 'location'; alert(location); // вернет 'location' alert(window.location); // вернет window.location window.a = 'переменная из функции'; >alert(a); // undefined foo(); alert(a); // переменная из функции
Наследование области видимости
Меня всегда смущало то, что в Javascript можно определять функции внутри функций, а использовать их потом где угодно. Ну да, если посмотреть, точно то же самое можно делать в Ruby, и, наверное, во многих других языках тоже.
Переменные при этом передаются очень просто: если на момент определения функции переменная существовала, то она будет существовать и внутри функции. Откуда бы ее не вызывали.
function alertOnTimeout(message, timeout) < return setTimeout(function() < // message будет доступен в безымянной функции, переданной таймауту alert(message); >, timeout); >
Передача кода по старинке — строкой, которая прогоняется через eval() — не попадает под это правило, код исполняется в той области видимости, где и определен.
Поскольку объекты в Javascript — это тоже типа функции, то свойство объекта определяется точно так же, как и переменная.
А еще в Javascript область видимости переменной ограничивается только функциями, а не блоками типа if (привет, Паскаль). Потому удобнее всего объявлять переменные в начале функции.
this
А что this ? А то, что эта переменная автоматически появляется в методах объектов и затирает значение this из предыдущей области видимости. Решение простое — переприсваивать ее значение другой переменной.
$('div.with-links').click(function() < var theDiv = this; //сохраняем значение this $(this).find('a').click(function() < alert($(this).attr('href')); // this - это ссылка theDiv.remove(); // а theDiv - это все еще дивак >); >);
Отдельно замечу, что при оборачивании какой-то поведенческой логики в объект надо помнить, что в создаваемых DOM-событиях значение this самого объекта теряется.