Кратко
Секция статьи "Кратко"Переменные в JavaScript хранят значения, которыми оперирует код. Для создания переменных используются ключевые слова var
, let
и const
.
Что такое переменные
Секция статьи "Что такое переменные"Переменные — это именованные контейнеры для хранения данных.
Для создания переменной используется ключевое слово let
, const
или var
. Сразу за ключевым словом идёт название переменной либо перечень переменных через запятую. Создание переменной также называют объявлением переменной. Например:
var singleVariablelet firstVariable, secondVariable, thirdVariable
var singleVariable let firstVariable, secondVariable, thirdVariable
Чаще всего, при объявлении переменной ей устанавливают стартовое значение при помощи оператора присваивания
. Тип значения может быть абсолютно любым — строка, число, объект, массив и так далее.
// Объявление переменной и присваиваниеlet string = 'foo'const array = ['foo', 'bar', 'baz']var number = 10// Множественное объявление и присваиваниеlet firstNumber = 5, secondNumber = 10
// Объявление переменной и присваивание let string = 'foo' const array = ['foo', 'bar', 'baz'] var number = 10 // Множественное объявление и присваивание let firstNumber = 5, secondNumber = 10
Затем переменную можно использовать как заменитель значения в коде:
let name = 'Уолтер'let surname = 'Вайт'let fullName = name + ' ' + surnameconsole.log(fullName)// Уолтер Вайт
let name = 'Уолтер' let surname = 'Вайт' let fullName = name + ' ' + surname console.log(fullName) // Уолтер Вайт
Правила именования переменных
Секция статьи "Правила именования переменных"Для имени переменной можно использовать следующие символы:
- буквы латинского алфавита;
- цифры;
- символы
$
и
._
Первый символ не должен быть цифрой:
let letters, &ersand, _underscorelet 1number// SyntaxError: Invalid or unexpected token
let letters, &ersand, _underscore let 1number // SyntaxError: Invalid or unexpected token
В качестве названий переменных нельзя использовать зарезервированные языком слова. Например: class
, super
, throw
, yield
, var
, let
, const
и так далее. С полным списком таких слов можно ознакомиться здесь.
Создание переменных
Секция статьи "Создание переменных"Перед выполнением скрипта JavaScript находит код создания переменных и заранее создаёт их. Получается, что в начале выполнения скрипта все переменные, описанные в коде, уже объявлены. В зависимости от браузера, они могут быть равны undefined
(в Chrome и Safari), либо, в случае с let
и const
в браузере Firefox, не равны ничему и иметь специальное состояние uninitialized
:
console.log('Старт')var byVar = 5let byLet = 10const byConst = 15console.log('Конец')
console.log('Старт') var byVar = 5 let byLet = 10 const byConst = 15 console.log('Конец')
В конце скрипта, после того как произошло присвоение стартовых значений, переменные равны 5
, 10
и 15
:
Получается, что некоторое время переменная может содержать значение undefined
и быть доступной для чтения. Этим нужно пользоваться с осторожностью.
Переменные let
и const
Секция статьи "Переменные let и const" Переменные let
и const
появились в версии EcmaScript 2015 года (ES6), пришли на смену устаревшему var
.
Объявление
Секция статьи "Объявление"Используя ключевое слово let
, можно объявить переменную без присвоения ей начального значения. В таком случае она будет равна undefined
:
let aconsole.log(a)// undefineda = 5console.log(a)// 5
let a console.log(a) // undefined a = 5 console.log(a) // 5
При помощи const
нельзя объявлять переменные без значения:
const a// SyntaxError: Missing initializer in const declaration// Правильноconst b = 5
const a // SyntaxError: Missing initializer in const declaration // Правильно const b = 5
К переменным let
и const
нельзя обращаться до их объявления в коде:
console.log(a)// ReferenceError: Cannot access 'a' before initializationconsole.log(b)// ReferenceError: Cannot access 'b' before initializationlet a = 5const a = 5
console.log(a) // ReferenceError: Cannot access 'a' before initialization console.log(b) // ReferenceError: Cannot access 'b' before initialization let a = 5 const a = 5
Почему так?
У let
и const
есть так называемая temporal dead zone (TDZ) — момент выполнения скрипта до объявления переменной. Переменная может находиться и выше объявления, при условии, что содержащая её часть кода будет выполнена после инициализации:
function foo() { console.log('from foo', a)}Promise.resolve() .then(() => console.log('from promise', a))setTimeout(() => console.log('from timer',a))let a = 10foo()// 'from foo 10', 'from promise 10', 'from timer 10'
function foo() { console.log('from foo', a) } Promise.resolve() .then(() => console.log('from promise', a)) setTimeout(() => console.log('from timer',a)) let a = 10 foo() // 'from foo 10', 'from promise 10', 'from timer 10'
TDZ есть также и у es6
-классов, несмотря на то, что они являются «синтаксическим сахаром» над обычными функциями.
console.log(Foo)class Foo { constructor(bar) { this.bar = bar }}// ReferenceError: Cannot access 'Foo' before initialization
console.log(Foo) class Foo { constructor(bar) { this.bar = bar } } // ReferenceError: Cannot access 'Foo' before initialization
А функции (объявленные как Function Declaration) TDZ не имеют.
console.log(Foo)function Foo() { this.bar = bar}// ƒ Foo() { this.bar = bar}
console.log(Foo) function Foo() { this.bar = bar } // ƒ Foo() { this.bar = bar}
Оба типа переменных имеют блочную область видимости и не становятся частью глобального объекта (window
в браузере, global
в Node.js). Блочная область видимости не даёт получить значение переменной вне блока, где она была объявлена.
Если объявить переменные внутри блока if
, то обращение к ним вне блока будет выбрасывать ошибку:
if (true) { let a = 5 const b = 10 console.log(a) // 5 console.log(b) // 10}console.log(a)// ReferenceError: a is not definedconsole.log(b)// ReferenceError: b is not defined
if (true) { let a = 5 const b = 10 console.log(a) // 5 console.log(b) // 10 } console.log(a) // ReferenceError: a is not defined console.log(b) // ReferenceError: b is not defined
Одинаковые имена переменных
Секция статьи "Одинаковые имена переменных"Объявление переменной с именем, которое уже используется в текущей области видимости, приведёт к ошибке:
let a = 5let a = 10// SyntaxError: Identifier 'a' has already been declared
let a = 5 let a = 10 // SyntaxError: Identifier 'a' has already been declared
То же правило работает и при использовании const
, и при использовании смешанного подхода:
const a = 5const a = 10// SyntaxError: Identifier 'a' has already been declaredvar b = 5const b = 10// SyntaxError: Identifier 'b' has already been declared
const a = 5 const a = 10 // SyntaxError: Identifier 'a' has already been declared var b = 5 const b = 10 // SyntaxError: Identifier 'b' has already been declared
В то же время можно объявлять переменные с одинаковым именем в разных областях видимости. В этом случае значение будет зависеть от той области видимости, где происходит чтение:
let name = 'Ольга'if (true) { let name = 'Елена' console.log(name) // Елена}console.log(name)// Ольга
let name = 'Ольга' if (true) { let name = 'Елена' console.log(name) // Елена } console.log(name) // Ольга
Смена значения в let
и const
Секция статьи "Смена значения в let и const" Значение в переменной, созданной через let
, можно изменять:
let a = 5console.log(5)// 5a = 10console.log(a)// 10
let a = 5 console.log(5) // 5 a = 10 console.log(a) // 10
Стартовое значение const
изменить нельзя, будь то примитивное значение:
const a = 5a = 10// TypeError: Assignment to constant variable
const a = 5 a = 10 // TypeError: Assignment to constant variable
Или ссылка на объект:
const obj = { a: 5,}obj = { a: 10,}// TypeError: Assignment to constant variable
const obj = { a: 5, } obj = { a: 10, } // TypeError: Assignment to constant variable
Однако объект, хранящийся в const
, можно мутировать. Объекты хранятся по ссылке, и изменение объекта не приводит к изменению ссылки на него:
const obj = { a: 5,}obj.a = 10console.log(obj)// { a: 10 }
const obj = { a: 5, } obj.a = 10 console.log(obj) // { a: 10 }
Переменные var
Секция статьи "Переменные var" Объявление переменных при помощи ключевого слова var
было в JavaScript с первых версий.
Объявление
Секция статьи "Объявление"Переменные var
можно объявлять без присвоения им значения, в таком случае они будут равны undefined
:
var aconsole.log(a)// undefinedvar b = 5console.log(b)// 5
var a console.log(a) // undefined var b = 5 console.log(b) // 5
Переменные, объявленные через var
, имеют функциональную область видимости. Они доступны только в пределах текущей функции или глобального объекта, если функции нет:
if (true) { var a = 5}function foo() { var b = 10}console.log(a)// 5console.log(b)// ReferenceError: b is not defined
if (true) { var a = 5 } function foo() { var b = 10 } console.log(a) // 5 console.log(b) // ReferenceError: b is not defined
Объявление переменной вне функций делает их глобальными переменными. Они доступны как свойства глобального объекта:
var varVariable = 5console.log(window.varVariable)// 5
var varVariable = 5 console.log(window.varVariable) // 5
К переменным, объявленным при помощи ключевого слова var
, можно обращаться до момента объявления. В отличие от let
и const
, ошибки это не вызовет. Такое поведение называется hoisting - «всплытие»:
console.log(a)// undefinedvar a = 5console.log(a)// 5
console.log(a) // undefined var a = 5 console.log(a) // 5
Разберём, как работает функциональная область видимости:
var a = 5function foo() { console.log(a) // undefined var a = 10 console.log(a) // 10}foo()console.log(a)// 5
var a = 5 function foo() { console.log(a) // undefined var a = 10 console.log(a) // 10 } foo() console.log(a) // 5
Перед выполнением функции в глобальной области видимости присутствует переменная a
, равная 5
:
Во время выполнения функции формируется новая функциональная область видимости, в которой тоже присутствует переменная a
. Эта переменная была объявлена с помощью var
внутри функции, в момент выполнения которой она «всплыла» со значением равным undefined
. В строке 4 происходит обращение именно к ней (до её объявления), а не к той, что находится вне функции.
В строке 8 значение переменной a
уже равно 10.
После выполнения функции локальная область видимости была удалена. В консоли выводится глобальная переменная a
.
Более подробно об этом можно прочитать в отдельной статье
Смена значения в var
Секция статьи "Смена значения в var" Значение, хранящееся в переменной var
, можно изменить двумя способами:
- обратиться к имени переменной и присвоить новое значение:
var a = 5console.log(a)// 5a = 10console.log(a)// 10
var a = 5 console.log(a) // 5 a = 10 console.log(a) // 10
- обратиться к имени переменной вместе с ключевым словом
var
:
var a = 5console.log(a)// 5var a = 10console.log(a)// 10
var a = 5 console.log(a) // 5 var a = 10 console.log(a) // 10
На практике
Секция статьи "На практике"🛠 В новом коде используйте только let
или const
. Используйте let
в тех случаях, когда значение переменной меняется. Во всех остальных используйте const
. Проще всего всегда по умолчанию использовать ключевое слово const
и исправлять объявление переменной на let
, если появляется нужда изменить её значение далее в коде.
🛠 Называйте переменные так, чтобы можно было легко понять, что в них хранится. Например:
let url = 'https://doka.guide'const now = Date.now()const user = { name: 'John', age: 30,}
let url = 'https://doka.guide' const now = Date.now() const user = { name: 'John', age: 30, }
Исключением считается именование счётчиков в циклах for
, в которых обычно используются одиночные буквы i
, j
, и так далее.
Имена переменных могут состоять из нескольких слов, поэтому для удобства их чтения в JavaScript принято использовать так называемую «верблюжью нотацию» (camelCase), когда каждое новое слово, начиная со второго, пишется с заглавной буквы:
const fullName = 'John Doe'const arrayOfNumbers = [1, 2, 3]
const fullName = 'John Doe' const arrayOfNumbers = [1, 2, 3]
Имена констант (переменные, которые не меняют своё значение) принято писать, используя screaming_snake_case. В данной нотации все слова пишутся заглавными буквами, а разделителем является символ
.
const BASE_URL = 'https://doka.guide'const PORT = 3000const UNAUTHORIZED_CODE = 401
const BASE_URL = 'https://doka.guide' const PORT = 3000 const UNAUTHORIZED_CODE = 401