В редакцию ES2015 были введены два новых важных ключевых слова JavaScript — let и const.
Эти два ключевых слова позволяют в JavaScript декларировать переменные и константы с областью видимости внутри блока.
До редакции ES2015 в JavaScript было только два типа области видимости — глобальная и внутри функции.
Глобальная область видимости
Переменные, декларированные глобально (вне какой-либо функции), обладают глобальной областью видимости.
Пример:
var carName = "Volvo";
// расположенный здесь код может использовать переменную carName
function myFunction() {
// расположенный здесь код также может использовать переменную carName
}
Доступ к глобальным переменным можно получить из любого места программы на JavaScript.
Область видимости внутри функции
Переменные, декларированные локально (внутри какой-либо функции), обладают областью видимости внутри функции.
Пример:
// расположенный здесь код не может использовать переменную carName
function myFunction() {
var carName = "Volvo";
// расположенный здесь код может использовать переменную carName
}
Доступ к локальным переменным можно получить только внутри той функции, где эти переменные были декларированы.
Область видимости внутри блока
Переменные, декларированные при помощи ключевого слова var, не обладают областью видимости внутри блока.
Т.е. доступ к таким переменным, декларированным внутри блока { }, можно получить и вне этого блока.
Пример:
{
var x = 2;
}
// здесь переменную x МОЖНО использовать
До редакции ES2015 в JavaScript не было области видимости внутри блока.
Начиная с редакции ES2015 переменные, декларированные при помощи ключевого слова let, приобретают область видимости внутри блока. В результате этого переменные, декларированные таким образом внутри блока { }, становятся недоступными за пределами этого блока.
Пример:
{
let x = 2;
}
// здесь переменную x НЕЛЬЗЯ использовать
Передекларирование переменных
Передекларирование переменной при помощи ключевого слова var может вызвать проблемы.
Так, если передекларировать переменную внутри блока, то она будет перекларирована и за его пределами:
var x = 10;
// Здесь значение x равно 10
{
var x = 2;
// Здесь значение x равно 2
}
// Здесь значение x равно 2
Решить эту проблему можно, если передекларировать переменную при помощи ключевого слова let.
В этом случае передекларирование переменной внутри блока не будет передекларировать переменную за пределами этого блока:
var x = 10;
// Здесь значение x равно 10
{
let x = 2;
// Здесь значение x равно 2
}
// Здесь значение x равно 10
Область видимости внутри цикла
Использование ключевого слова var в цикле:
var i = 5;
for (var i = 0; i < 10; i++) {
// какой-то код
}
// Здесь значение i равно 10
Использование ключевого слова let в цикле:
let i = 5;
for (let i = 0; i < 10; i++) {
// какой-то код
}
// Здесь значение i равно 5
В первом примере переменная, декларированная в цикле при помощи ключевого слова var, также передекрарирует переменную за пределами цикла.
Во втором примере переменная, декларированная в цикле с ключевым словом let, не передекрарирует переменную за пределами цикла, оставляя неизменным ее значение, так как использование ключевого слова let для декларирования переменной i в цикле делает переменную i видимой только внутри этого цикла.
Область видимости внутри функции
Поведение переменных, декларированных внутри функции при помощи ключевых слов var и let, одинаковое. В обоих случаях у переменных будет локальная область видимости.
function myFunction() {
var carName = "Volvo"; // Область видимости внутри функции
}
function myFunction() {
let carName = "Volvo"; // Область видимости внутри функции
}
Глобальная область видимости
Поведение переменных, декларированных вне блока при помощи ключевых слов var и let, одинаковое. В обоих случаях у переменных будет глобальная область видимости.
var x = 2; // Глобальная область видимости
let x = 2; // Глобальная область видимости
Глобальные переменные в HTML
В JavaScript глобальная область видимости распространяется на все окружение JavaScript.
В HTML глобальная область видимости — это глобальный объект window.
Глобальные переменные, декларированные при помощи ключевого слова var, принадлежат глобальному объекту window:
var carName = "Volvo";
// здесь код может использовать window.carName
Глобальные переменные, декларированные при помощи ключевого слова let, не принадлежат глобальному объекту window:
let carName = "Volvo";
// здесь код не может использовать window.carName
Передекларирование
Передекларировать переменную JavaScript при помощи ключевого слова var можно в любом месте программы:
var x = 2;
// Значение x равно 2
var x = 3;
// Теперь значение x равно 3
Нельзя передекларировать переменную, которая была декларирована при помощи ключевого слова var, при помощи ключевого слова let в той же области видимости или в том же блоке:
var x = 2; // Можно
let x = 3; // Нельзя
{
var x = 4; // Можно
let x = 5 // Нельзя
}
Нельзя передекларировать переменную, которая была декларирована при помощи ключевого слова let, при помощи ключевого слова let в той же области видимости или в том же блоке:
let x = 2; // Можно
let x = 3; // Нельзя
{
let x = 4; // Можно
let x = 5; // Нельзя
}
Нельзя передекларировать переменную, которая была декларирована с ключевым словом let, при помощи ключевого слова var в той же области видимости или в том же блоке:
let x = 2; // Можно
var x = 3; // Нельзя
{
let x = 4; // Можно
var x = 5; // Нельзя
}
Передекларировать переменную при помощи ключевого слова let в другой области видимости или в другом блоке можно:
let x = 2; // Можно
{
let x = 3; // Можно
}
{
let x = 4; // Можно
}
Поднятие
Переменные, декларированные при помощи ключевого слова var, "поднимаются" в верх JavaScript кода (если вы не знаете, что такое "поднятие" в JavaScript, то см. главу Поднятие переменных в Javascript).
Таким образом, мы можем использовать такие переменные до того, как они будут декларированы:
// здесь МОЖНО использовать carName
var carName;
Переменные, декларированные при помощи ключевого слова let, не "поднимаются" в верх JavaScript кода.
Использование переменной, декларированной при помощи ключевого слова let, до ее реальной декларации приведет к ошибке ReferenceError.
В этом случае такая переменная находится в, так называемой, "временной мертвой зоне" с начала блока и до ее декларации:
// здесь НЕЛЬЗЯ использовать carName
let carName;