Готовый перевод Modern JS Cheatsheet / Памятка по современному JavaScript: Объявление переменных
### Объявление переменных: var, const, let
В JavaScript три ключевых слова, отвечающих за объявление переменных, и у каждого из них свои особенности. Эти слова - "var", "let" и "const".
#### Краткое объяснение
Переменным, объявленным с помощью ключевого слова ```const```, нельзя позднее присвоить новое значение, в то время как переменным, объявленным с помощью ```let``` или ```var```, можно.
Я рекомендую всегда объявлять переменные ключевым словом "const", а "let" использовать только в том случае, если позже эту переменную понадобится *изменить* или переопределить.
<table>
<tr>
<th></th>
<th>Область видимости</th>
<th>Можно переопределять</th>
<th>Можно изменять</th>
<th><a href="#tdz_sample">Временная мертвая зона</a></th>
</tr>
<tr>
<th>const</th>
<td>Блок</td>
<td>Нет</td>
<td><a href="#const_mutable_sample">Да</a></td>
<td>Да</td>
</tr>
<tr>
<th>let</th>
<td>Блок</td>
<td>Да</td>
<td>Да</td>
<td>Да</td>
</tr>
<tr>
<th>var</th>
<td>Функция</td>
<td>Да</td>
<td>Да</td>
<td>Нет</td>
</tr>
</table>
#### Пример кода
Вызовет ошибку, переменной "person" нельзя присвоить новое значение
присвоение нового значения разрешено в случае с let
#### Подробное объяснение
[*Область видимости*](#scope_def) переменной определяет, где эта переменная доступна в коде.
##### var
Областью видимости переменных, объявленных с помощью ```var```, является функция. Это означает, что если переменная была создана внутри функции, то у всего внутри этой функции есть доступ к этой переменной. Кроме того, переменная с областью видимости внутри функции недоступна за пределами этой функции.
Можно думать об этом вот так: если у переменной область видимости *Х*, то эта переменная - как бы свойство Х.
```javascript
function myFunction() {
var myVar = "Коля";
console.log(myVar); // "Коля" - к myVar есть доступ изнутри функции
}
console.log(myVar); // Undefined, извне доступа к myVar нет.
```
Вот несколько менее очевидный пример области видимости переменных:
// действительно, myVar имеет область видимости внутри функции, мы всего лишь удалили предыдущее значение переменной myVar "Nick" и заменили его на "John"
// "John" - обратите внимание, как код в блоке "if" повлиял на это значение
// Выдаст ошибку, переменная myVar недоступна за пределами функции, в которой определена
Кроме этого, переменные, объявленные ключевым словом *var*, при исполнении кода перемещаются в начало области видимости. Это называется [поднятие переменных](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/var#Поднятие_переменных).
Этот фрагмент кода:
```js
console.log(myVar) // undefined -- ошибок нет
var myVar = 2;
```
при исполнении понимается как:
```js
var myVar;
console.log(myVar) // undefined -- ошибок нет
myVar = 2;
```
##### let
```var``` и ```let``` очень похожи друг на друга, но переменные, объявленные словом ```let```:
- имеют в качестве области видимости блок
- **недоступны** до объявления
- не могут быть повторно объявлены в той же области видимости
Давайте разберем, насколько важна блоковая область видимости, на том же самом примере:
```javascript
function myFunction() {
let myVar = "Коля";
if (true) {
let myVar = "Ваня";
console.log(myVar); // "Ваня"
// Поскольку myVar имеет блоковую область видимости, здесь мы только что создали новую переменную myVar.
// Эта переменная недоступна вне блока и никаким образом не зависит
// от первой переменной myVar, которую мы создали до этого!
}
console.log(myVar); // "Коля" - видите, инструкции в блоке if НЕ повлияли на значение переменной
}
console.log(myVar); // Undefined, доступа к myVar извне функции нет.
```
<a name="tdz_sample"></a> Теперь посмотрим, что значит "переменные, объявленные словами "let" и "const", недоступны до их объявления":
```js
console.log(myVar) // вызывает ReferenceError !
let myVar = 2;
```
В отличие от переменных, объявленных с помощью *var*, если вы попытаетесь прочитать или записать переменную, объявленную с помощью *let* или *const*, до того, как ей будет присвоено значение, произойдёт ошибка. Этот феномен часто называют [*Временной мёртвой зоной*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_Dead_Zone_and_errors_with_let).
**Примечание:** строго говоря, объявления переменных с использованием *let* и *const* тоже поднимаются, однако их инициализация — нет. Они сделаны так, что использовать их до объявления нельзя. Поэтому интуитивно ощущается так, будто эти переменные не поднимаются — но это не так. Ищите больше информации в [этом очень подробном объяснении](http://jsrocks.org/2015/01/temporal-dead-zone-tdz-demystified), если хотите знать больше.
В дополнение к сказанному, вы не можете переобъявить переменную, объявленную с помощью *let*:
```js
let myVar = 2;
let myVar = 3; // Вызывает SyntaxError
```
##### const
Переменные, объявленные ключевым словом "const", ведут себя так же, как переменные *let*, только их еще и нельзя переопределять.
Подводя итог, переменные объявленные с помощью *const*:
- имеют в качестве области видимости блок
- недоступны до объявления
- не могут быть повторно объявлены в той же области видимости
- не могут быть переопределены
```js
const myVar = "Коля";
myVar = "Ваня" // вызывает ошибку, переопределять переменную нельзя.
```
```js
const myVar = "Коля";
const myVar = "Ваня" // вызывает ошибку, объявить переменную можно только один раз.
```
<a name="const_mutable_sample"></a> Но есть одна тонкость: переменные, объявленные с помощью ```const```не являются [**неизменными**](#mutation_def) ! Конкретно это означает, что *объекты* и *массивы*, объявленные с помощью ```const```, **могут** быть изменены. .
В случае объектов:
```js
const person = {
name: 'Коля'
};
person.name = 'Ваня' // сработает! Переменная person не полностью переопределяется, а просто меняется
console.log(person.name) // "Ваня"
person = "Сандра" // вызывает ошибку, потому что переменные, объявленные словом "const", переопределять нельзя
```
В случае массивов:
```js
const person = [];
person.push('Ваня'); // сработает! Переменная person не полностью переопределяется, а просто меняется
console.log(person[0]) // "Ваня"
person = ["Коля"] // вызывает ошибку, потому что переменные, объявленные словом "const", переопределять нельзя
```
#### Внешние ресурсы
- [Область видимости let и const в JavaScript - WesBos](http://wesbos.com/javascript-scoping/)
- [Демистификация временной мертвой зоны](http://jsrocks.org/2015/01/temporal-dead-zone-tdz-demystified)
Переведено на Нотабеноиде
http://notabenoid.org/book/70916/381874
Переводчики: Tomatoknight, a_popova, wizjer
Настройки
Готово:
