Сравнительно небольшая статья будет. Хочу упомянуть про видимость переменных в коде. Стоит отнестись внимательно к этой теме, чтобы потом не думать "почему так-то?!".
Начнем с простого примера.
Представим себе школу с классами от первого до одиннадцатого и возьмем отдельно взятый класс начальной школы. В классе у нас будут дети, которые разбиты учителем на группы с индивидуально-групповыми заданиями. Все при деле, все заняты.
Итак, ученики в своей группе точно знают, чем занимаются другие дети, работающие над заданием вместе с ними. При этом чем заняты другие группы в их классе они не в курсе - там же другие процессы решения задач происходят.
А вот кто знает про всех - это классный руководитель. Именно он раздаёт задания и контролирует их выполнение.
Вроде просто. Идем дальше. В параллели пусть будет три класса, каждый из которых работает по аналогичной учебной программе, а всего в начальной школе 12 классов. Классный руководитель нашего класса не знает, что там и как в соседнем - это область ответственности других учителей. Однако, есть тот, кто в курсе относительно всего учебного процесса во всех классах - это завуч начальной школы.
И опять "но": есть ведь старшая школа. Там свои группы, свои задания, свои варианты решений. Завуч старшей школы безусловно в курсе того, что происходит в его зоне ответственности. Но он не в курсе относительно того, что за дети в начальной школе.
А еще... Еще есть директорат: директор школы, методист и прочие люди, в чьи должностные обязанности входит контроль над всем учебным процессом и они вынужденно знают как учеников, так и чем они заняты и в каком состоянии находятся процессы изучения нового материала.
Разумеется, пример как говортится "из пальца". Но дает довольно точную картину того, как делятся зоны ответственности.
Теперь о предмете статьи.
Зоны ответственности, применительно к JS - это области видимости.
По пунктам, что тут было сделано и что получилось:
- Объявил глобальную переменную a, равную 100
- Вызвал функцию getVariableA_0() для получения значения глобальной переменной a
- Вызвал функцию getVariableA_1(), которая объявляет переменную с тем же именем a, равную 50 и выводит её в консоль
- Вывел в консоль проверку: глобальную a увеличил на 50.
Вывод из этого примера следующий: глобальная переменная и переменная в функции могут совпадать по имени, но оператор присвоения (var или let) создадут новую переменную, которая будет видна исключительно внутри функции. Она не переопределила глобальную a!
Еще один схожий вариант проверки:
На основе цикла, в котором счетчик i не меняется в цикле несмотря на то, что явным образом объявляется в функции getVariableI(value).
Но это был простой пример. Поговорим о более сложном. Очень часто у начинающих разработчиков возникают проблемы при передаче значения "по цепочке" или с использованием так называемых "замыканий" ("closure"). Поясню. Знает ли в нашем примере завуч абсолютно всех учеников в своей зоне ответственности? Ответ очевиден, что не досконально. Видел всех - да, но точно знает? Предположим, есть "тревожный" звоночек и завуч вызывает родителей на откровенный диалог. Как происходит? Образно говоря, завуч получает докладную записку с требованием разобраться. То есть до этого завуч мог знать в лицо или даже по фамилии ученика, но он был для неё не более чем "одним из" до тех пор, пока ученик не оказался в "области видимости".
В программировании на JS есть нечто подобное.
Есть к примеру такой оператор:
setTimeout(function() {<какой-то код>}, 1000);
Делает он следующее: переданная в него функция должна запуститься через 1000 миллисекунд (через 1 секунду). Задача: вывести числа от 1 до 10 в консоль с интервалом в 2 секунды.
Если сделаю вот так:
Вроде всё хорошо - выводит с диапазоном в 1 секунду, потому что число 0 должно вывестись сразу, ..., 2 - через 2 секунды, ... 7 - через 7 секунд, и т.д.
Только вот число выводится 10 десять раз, а должно от 0 до 9. Почему? Потому, что значение переменной i дошло до 10, что является первым значением, НЕ подходящим под условие i < 9. Цикл успел завершиться до того, как сработал первый setTimeout. И сама IDE подсказывает, что что-то не так:
Грубо говоря - не просто видно, но и меняется само по себе. Там всё сложней в объяснениях, но суть такая.
Решение проблемы на самом деле выглядит в создании отдельной функции, в которой значение i из цикла будет внутри области видимости только этой функции.
На самом деле тема намного шире, чем приведенные здесь примеры. Единственное, что хотел показать в этой статье - необходимость внимательно следить за тем, на каком уровне кода вы определяете свои переменные.
Все статьи попадают в "Оглавление канала". Не пропускаем новости!