Var, let, const, в чём разница? И как использовать?

Var, let, const, в чём разница? И как использовать?

Coding


До появления стандарта ECMAScript 6 у нас в распоряжении было только одно ключевое слово для объявления переменных — var.

Переменные, объявленные с помощью var, могут находиться:

  • Либо в области видимости функции, если они объявлены внутри функции. В этом случае они доступны только внутри функции, в которой объявлены.
  • Либо в глобальной области видимости, если они объявлены вне функции. В таком случае, они доступны где угодно.


/* глобальная переменная */
var test = 100;

(() => {
    /* локальная переменная, доступна только внутри функции */
    var test = 200;
    console.log(test); //200
})();

console.log(test); //100

В примере в первом случае переменная test объявлена в глобальной области видимости, а во втором — в локальной. Первый console.log выведет значение локальной переменной, а второй — глобальной.

Переменной, объявленной с помощью var, можно присвоить новое значение:

var test = 100;
console.log(test); //100

test = 200;
console.log(test); //200

И наконец, переменную, объявленную с помощью var, можно переобъявить, т.е. создать другую переменную с тем же именем в той же области видимости:

var test = 100;
console.log(test); //100

var test = 200;
console.log(test); //200

А теперь вернемся к первому примеру и выведем значение переменной, скажем, здесь:

var test = 100;

(() => {
    console.log(test); //undefined
    var test = 200;
    console.log(test); //200
})();

console.log(test); //100

Новый console.log выведет значение undefined. Это явление называется "подъемом переменных".

Интерпретатор JavaScript незаметно для нас «поднимает» объявления переменных в начало области видимости. В нашем случае, это начало функции.

Переменные, объявленные с помощью var, инициализируются значением undefined.

В ES6 появились два новых ключевых слова: let и const.


let

Ключевое слово let очень похоже на var, но все же имеет некоторые отличия. Начнем с того, что переменная, объявленная с помощью let попадает в область видимости уровня блока. Напомню, что блоком является часть кода, заключенная в фигурные скобки.

Взгляните на пример:

/* глобальная переменная */
let test = 100;

{
    /* локальная переменная, доступна только внутри блока */
    let test = 200;
    console.log(test); //200
}

console.log(test); //100

Здесь первая переменная test объявлена в глобальной области видимости, а вторая — в локальной области видимости уровня блока.

Переменным, объявленным с помощью let, можно присвоить новое значение.

let test = 100;
console.log(test); //100

test = 200;
console.log(test); //200

Но, в отличии от var, нельзя объявить еще одну переменную с тем же именем в той же области видимости:

let test = 100;
console.log(test);

let test = 200;
console.log(test);

Uncaught SyntaxError: Identifier 'test' has already been declared

При попытке переобъявить переменную, мы получим ошибку.

Зато каждый цикл создает свою область видимости, поэтому переменные с одним и тем же именем можно использовать в разных циклах:

for (let i = 0; i < 10; i++) { /* … */ }
for (let i = 0; i < 10; i++) { /* … */ }

Кстати, стоит отметить, что объявление цикла и тело цикла образуют две области видимости.

let i = 100;
for (let i = 0; i < 10; i++) {
    let i = 200;
    console.log(i); //200
}

В примере в консоль десять раз выведется значение 200.

Такое поведение let позволяет решить классическую задачу с замыканиями.

for (var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 10);
}

C var в примере мы получим в консоли десять раз значение 10. Но если заменим var на let, пример будет работать так, как и ожидается, и мы получим в консоли числа от 0 до 9.

for (let i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 10);
}

К объявлениям let также применяется подъем переменных, но сами переменные, в отличии от var, недоступны, пока не будут определены.

{
    /* переменная test здесь не инициализирована. Попытка доступа вызовет ошибку */
    let test = 5;
    // test равна 5
}

Это называется временная мертвая зона (temporal dead zone) переменной.


const

Ключевое слово const полностью аналогично let, но переменной, объявленной с помощью const, нельзя присвоить новое значение и нельзя объявить неинициализированную константу.

const test = 1;
test = 2;

Uncaught TypeError: Assignment to constant variable.

Тут стоит отметить, что если константой является объект, то изменять его свойства все же можно.

const foo = {};
foo.bar = 42;
console.log(foo.bar);

Нельзя присвоить константе другой объект.


Итак, подытожим.

Переменные, объявленные с помощью var, попадают в область видимости уровня функции, их можно изменять и переобъявлять.

Переменные, объявленные с помощью let, попадают в область видимости уровня блока, их можно изменять, но нельзя переобъявлять.

И наконец, переменные, объявленные с помощью const, попадают в область видимости уровня блока, их нельзя изменять или переобъявлять.

Какое же из ключевых слов использовать и в каком случае? Здесь мнения расходятся. Кто-то считает, что по умолчанию следует использовать const, let использовать только в том случае, если значение переменной должно обновляться, а var не стоит использовать вовсе, ну или в крайнем случае, в легаси-проектах.

А кто-то предпочитает по-старинке объявлять переменные с помощью var, а let использовать только тогда, когда переменная действительно используется исключительно в блоке.


Источник

Report Page