Понимание переменных, области видимости и подъема в JavaScript
Введение
Переменные являются фундаментальной частью многих языков программирования и являются одними из первых и наиболее важных понятий, которые должны изучать начинающие программисты. В JavaScript есть ряд различных свойств переменных, а также несколько правил, которым необходимо следовать при их именовании. В JavaScript для объявления переменной используются три ключевых слова — var
, let
и const
— и каждое из них влияет на интерпретацию кода. переменная по-разному.
В этом руководстве вы узнаете, что такое переменные, как их объявить и назвать, а также подробно рассмотрим разницу между var
, let
и const
. Мы также рассмотрим эффекты подъема и значение глобальной и локальной области действия для поведения переменной.
Понимание переменных
Тип данных JavaScript, включая число, строку или объект.
До своего собственного раздела ниже.
Мы можем использовать var
, чтобы продемонстрировать концепцию самой переменной. В приведенном ниже примере мы объявляем переменную и назначаем ей значение.
// Assign the string value Sammy to the username identifier
var username = "sammy_shark";
Это заявление состоит из нескольких частей:
- Объявление переменной с использованием ключевого слова
var
- Имя переменной (или идентификатор),
имя пользователя
- Операция присваивания, представленная синтаксисом
=
- Присваиваемое значение:
sammy_shark
Теперь мы можем использовать username
в коде. JavaScript запомнит, что username
представляет строковое значение sammy_shark
.
// Check if variable is equal to value
if (username === "sammy_shark") {
console.log(true);
}
Outputtrue
Как упоминалось ранее, переменные могут использоваться для представления любого типа данных JavaScript. В этом примере мы объявим переменные со строковыми, числовыми, объектными, логическими и нулевыми значениями.
// Assignment of various variables
var name = "Sammy";
var spartans = 300;
var kingdoms = [ "mammals", "birds", "fish" ];
var poem = { roses: "red", violets: "blue" };
var success = true;
var nothing = null;
Используя console.log
, мы можем увидеть значение, содержащееся в определенной переменной.
// Send spartans variable to the console
console.log(spartans);
Output300
Переменные хранят данные в памяти, к которым впоследствии можно получить доступ и изменить их. Переменные также можно переназначать и присваивать им новое значение. В приведенном ниже упрощенном примере показано, как пароль можно сохранить в переменной, а затем обновить.
// Assign value to password variable
var password = "hunter2";
// Reassign variable value with a new value
password = "hunter3";
console.log(password);
Output'hunter3'
В реальной программе пароль, скорее всего, надежно хранится в базе данных. Однако этот пример иллюстрирует ситуацию, в которой нам может понадобиться обновить значение переменной. Значением password
было hunter2
, но мы переназначили его hunter3
, что является значением, которое JavaScript распознает с этого момента.
Именование переменных
Имена переменных известны как идентификаторы в JavaScript. Мы обсудили несколько правил именования идентификаторов в разделе «Понимание синтаксиса и структуры кода в JavaScript», кратко изложенные здесь:
- Имена переменных могут состоять только из букв (
a–z
), цифр (0–9
), символов доллара ($
) и подчеркивания (_
) - Имена переменных не могут содержать пробельных символов (табуляции или пробелов)
- Числа не могут начинаться с имени какой-либо переменной.
- Есть несколько зарезервированных ключевых слов, которые нельзя использовать в качестве имени переменной.
- Имена переменных вводятся с учетом регистра
В JavaScript также существует соглашение об использовании верблюжьего регистра (иногда стилизованного под верблюжий регистр) в именах функций и переменных, объявленных с помощью var
или let
. Это практика написания первого слова строчными буквами, а затем заглавной буквы каждого последующего слова без пробелов между ними. Большинство переменных, которые не являются константами, будут следовать этому соглашению, за некоторыми исключениями. Имена постоянных переменных, объявленных с помощью ключевого слова const
, обычно пишутся в верхнем регистре.
Может показаться, что вам нужно выучить множество правил, но очень быстро вы станете второй натурой писать допустимые и общепринятые имена переменных.
Разница между var, let и const
В JavaScript есть три разных ключевых слова для объявления переменной, что добавляет дополнительный уровень сложности языку. Различия между ними основаны на объеме, подъеме и переназначении.
Keyword | Scope | Hoisting | Can Be Reassigned | Can Be Redeclared |
---|---|---|---|---|
var |
Function scope | Yes | Yes | Yes |
let |
Block scope | No | Yes | No |
const |
Block scope | No | No | No |
Вам может быть интересно, какой из трех вы должны использовать в своих собственных программах. Общепринятой практикой является максимальное использование const
и let
в случае циклов и переназначения. Как правило, var
можно не использовать вне работы с унаследованным кодом.
Область действия переменной
Область в JavaScript относится к текущему контексту кода, который определяет доступность переменных для JavaScript. Существует два типа области видимости: локальная и глобальная:
- Глобальные переменные — это переменные, объявленные вне блока.
- Локальные переменные – это переменные, объявленные внутри блока.
В приведенном ниже примере мы создадим глобальную переменную.
// Initialize a global variable
var creature = "wolf";
Мы узнали, что переменные можно переназначать. Используя локальную область, мы можем фактически создавать новые переменные с тем же именем, что и у переменной во внешней области, без изменения или переназначения исходного значения.
В приведенном ниже примере мы создадим глобальную переменную species
. Внутри функции есть локальная переменная с тем же именем. Отправив их в консоль, мы можем увидеть, как значение переменной отличается в зависимости от области видимости, а исходное значение не меняется.
// Initialize a global variable
var species = "human";
function transform() {
// Initialize a local, function-scoped variable
var species = "werewolf";
console.log(species);
}
// Log the global and local variable
console.log(species);
transform();
console.log(species);
Outputhuman
werewolf
human
В этом примере локальная переменная находится в области действия. Переменные, объявленные с помощью ключевого слова var
, всегда относятся к области действия функции, то есть они распознают функции как имеющие отдельную область действия. Таким образом, эта переменная с локальной областью недоступна из глобальной области.
Однако новые ключевые слова let
и const
имеют блочную область действия. Это означает, что новая локальная область действия создается из блоков любого типа, включая функциональные блоки, операторы if
и циклы for
и while
.
Чтобы проиллюстрировать разницу между переменными в области действия функции и блока, мы назначим новую переменную в блоке if
с помощью let
.
var fullMoon = true;
// Initialize a global variable
let species = "human";
if (fullMoon) {
// Initialize a block-scoped variable
let species = "werewolf";
console.log(`It is a full moon. Lupin is currently a ${species}.`);
}
console.log(`It is not a full moon. Lupin is currently a ${species}.`);
OutputIt is a full moon. Lupin is currently a werewolf.
It is not a full moon. Lupin is currently a human.
В этом примере переменная species
имеет одно глобальное значение (human
) и другое локальное значение (werewolf
). Однако если бы мы использовали var
, результат был бы другим.
// Use var to initialize a variable
var species = "human";
if (fullMoon) {
// Attempt to create a new variable in a block
var species = "werewolf";
console.log(`It is a full moon. Lupin is currently a ${species}.`);
}
console.log(`It is not a full moon. Lupin is currently a ${species}.`);
OutputIt is a full moon. Lupin is currently a werewolf.
It is not a full moon. Lupin is currently a werewolf.
В результате этого примера и глобальная переменная, и переменная блочной области действия получают одно и то же значение werewolf
. Это связано с тем, что вместо создания новой локальной переменной с помощью var
вы переназначаете ту же переменную в той же области. var
не распознает if
как часть другой, новой области. Обычно рекомендуется объявлять переменные с блочной областью действия, поскольку они создают код, который с меньшей вероятностью непреднамеренно переопределит значения переменных.
Подъем
В большинстве примеров мы использовали var
для объявления переменной, и мы инициализировали ее со значением. После объявления и инициализации мы можем получить доступ к переменной или переназначить ее.
Если мы попытаемся использовать переменную до того, как она была объявлена и инициализирована, она вернет undefined
.
// Attempt to use a variable before declaring it
console.log(x);
// Variable assignment
var x = 100;
Outputundefined
Однако, если мы опускаем ключевое слово var
, мы больше не объявляем переменную, а только инициализируем ее. Он вернет ReferenceError
и остановит выполнение скрипта.
// Attempt to use a variable before declaring it
console.log(x);
// Variable assignment without var
x = 100;
OutputReferenceError: x is not defined
Причина этого связана с подъемом, поведением JavaScript, при котором объявления переменных и функций перемещаются в верхнюю часть их области видимости. Поскольку поднимается только фактическое объявление, а не инициализация, значение в первом примере возвращает undefined
.
Чтобы продемонстрировать эту концепцию более четко, ниже приведен код, который мы написали, и то, как JavaScript фактически интерпретировал его.
// The code we wrote
console.log(x);
var x = 100;
// How JavaScript interpreted it
var x;
console.log(x);
x = 100;
JavaScript сохранил x
в памяти как переменную перед выполнением скрипта. Поскольку он все еще вызывался до того, как был определен, результатом будет undefined
, а не 100
. Однако это не вызывает ReferenceError
и не останавливает скрипт. Хотя ключевое слово var
на самом деле не изменило местоположение var
, это полезное представление о том, как работает подъем. Однако такое поведение может вызвать проблемы, потому что программист, написавший этот код, вероятно, ожидает, что вывод x
будет 100
, хотя вместо этого undefined
.
Мы также можем увидеть, как подъем может привести к непредсказуемым результатам в следующем примере:
// Initialize x in the global scope
var x = 100;
function hoist() {
// A condition that should not affect the outcome of the code
if (false) {
var x = 200;
}
console.log(x);
}
hoist();
Outputundefined
В этом примере мы объявили x
равным 100
глобально. В зависимости от оператора if
x
может измениться на 200
, но поскольку условие было false
, оно не должно было повлияло на значение x
. Вместо этого x
был поднят наверх функции hoist()
, и значение стало undefined
.
Этот тип непредсказуемого поведения потенциально может привести к ошибкам в программе. Поскольку let
и const
имеют блочную область видимости, они не будут подниматься таким образом, как показано ниже.
// Initialize x in the global scope
let x = true;
function hoist() {
// Initialize x in the function scope
if (3 === 4) {
let x = false;
}
console.log(x);
}
hoist();
Outputtrue
Повторное объявление переменных, которое возможно с помощью var
, вызовет ошибку с помощью let
и const
.
// Attempt to overwrite a variable declared with var
var x = 1;
var x = 2;
console.log(x);
Output2
// Attempt to overwrite a variable declared with let
let y = 1;
let y = 2;
console.log(y);
OutputUncaught SyntaxError: Identifier 'y' has already been declared
Подводя итог, можно сказать, что переменные, представленные с помощью var
, потенциально могут подвергаться воздействию подъема — механизма в JavaScript, в котором объявления переменных сохраняются в памяти. Это может привести к неопределенным переменным в коде. Введение let
и const
решает эту проблему, выдавая ошибку при попытке использовать переменную перед ее объявлением или при попытке объявить переменную более одного раза.
Константы
Во многих языках программирования есть константы, которые представляют собой значения, которые нельзя изменить или изменить. В JavaScript идентификатор const
создан по образцу констант, и значения, присвоенные const
, не могут быть переназначены.
Общепринято записывать все идентификаторы const
в верхнем регистре. Это помечает их как легко отличимые от других значений переменных.
В приведенном ниже примере мы инициализируем переменную SPECIES
как константу с помощью ключевого слова const
. Попытка переназначить переменную приведет к ошибке.
// Assign value to const
const SPECIES = "human";
// Attempt to reassign value
SPECIES = "werewolf";
console.log(SPECIES);
OutputUncaught TypeError: Assignment to constant variable.
Поскольку значения const
не могут быть переназначены, их необходимо объявить и инициализировать одновременно, иначе также будет выдана ошибка.
// Declare but do not initialize a const
const TODO;
console.log(TODO);
OutputUncaught SyntaxError: Missing initializer in const declaration
Значения, которые нельзя изменить в программировании, называются неизменяемыми, а значения, которые можно изменить, называются изменяемыми. Хотя значения const
нельзя переназначить, они изменяемы, поскольку можно изменить свойства объектов, объявленных с помощью const
.
// Create a CAR object with two properties
const CAR = {
color: "blue",
price: 15000
}
// Modify a property of CAR
CAR.price = 20000;
console.log(CAR);
Output{ color: 'blue', price: 20000 }
Константы полезны для того, чтобы дать понять себе в будущем и другим программистам, работающим с вами над проектом, что предполагаемая переменная не должна быть переназначена. Если вы ожидаете, что переменная может быть изменена в будущем, вы, вероятно, захотите использовать let
для объявления переменной.
Заключение
В этом руководстве мы рассмотрели, что такое переменная, правила именования переменных и способы переназначения значений переменных. Мы также узнали об области действия и подъеме, некоторых ограничениях исходного ключевого слова var
, а также о том, как let
и const
решают эти проблемы.
Чтобы сравнить, как переменные используются в других языках, вы можете прочитать наш учебник «Как использовать переменные в Python 3».