Готовый перевод 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

Настройки

Готово:

100.00% КП = 1.5