a)
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 1);
}
b)
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 1);
}
a) a) 0 1 2 3 4; b) 5 5 5 5 5
b) a) 5 5 5 5 5; b) 0 1 2 3 4
c) a) 5 5 5 5 5; b) 5 5 5 5 5
Розгорнути правильну відповідь з поясненням
Для початку потрібно розібратися у чому різниця між var
та let
. Область видимості змінної, оголошеної через var
, це її поточний контекст виконання. Який може обмежуватися функцією чи бути глобальним, для змінних, оголошених поза функцією. Але у var
є одна слабкість. Розглянемо її на прикладі нижче.
var greeting = 'say hi';
var times = 4;
if (times > 3) {
var greeting = 'say Hello instead';
}
console.log(greeting); // "say Hello instead"
Як видно, оскільки умова times > 3
повертає значення true
, значення змінної greeter
перевизначається як 'say Hello instead'
. Якщо ви несвідомо використаєте greeting
в інших ділянках коду, ви отримаєте непередбачуванний результат. Це може викликати безліч помилок у вашому коді. Ось чому виникає потреба в let
та const
.
let
має блокову область видимості. Блок – це фрагмент коду, обмежений фігурними дужками {}
. Все, що знаходиться всередині фігурних дужок, відноситься до блоку. Таким чином, змінна, оголошена в блоці через let
, буде доступна лише усередині цього блоку. Давайте тепер розглянемо ще один приклад.
let times = 4;
if (times > 3) {
let greeting = 'say Hello';
console.log(greeting); // "say Hello"
}
console.log(greeting); // ReferenceError: greeting is not defined
З цього прикладу видно, що спроба використати greeting
поза блоком (фігурних дужок, у межах яких змінна була визначена) поверне помилку, через те що let
має блокову область видимості.
Тож повернемося до завдання. Оскільки setTimeout
виконується асинхронно, а одна мілісекунда це дуже довгий час для комп’ютера, то переданний колбек викличеться вже після виконання циклу.
У випадку a змінна i
оголошується за допомогою ключового слова var
, тому вона є глобальною. Вона буде перезаписуватися кожну ітерацію, а коли викличеться setTimeout
, буде мати своє останнє значення - 5
, тож у консоль послідовно виведеться 5 5 5 5 5
.
У випадку b змінна i
вже оголошена через let
і має блокову область видимості. Тобто вона є доступною лише в області видимості циклу for
. Під час кожної ітерації змінна матиме нове значення, а після виконання коду у консоль виведеться 0 1 2 3 4
.
Отже правильна відповідь a) 5 5 5 5 5; b) 0 1 2 3 4