Что выведет console.log в результате выполнения цикла while?

Дан код:

var i = 10;
var array = [];

while (i--) {
    (function (i) {
        var i = i;
        array.push(function() {
            return i + i;
        });
    })(i);
}    

console.log([
    array[0](),
    array[1](),
])

Что выведет console.log в результате выполнения кода?

Теория по задаче

Для понимания поведения представленного кода важно разобраться в ключевых концепциях JavaScript, таких как замыкания, IIFE (немедленные) функции и циклы. Давайте рассмотрим каждый аспект подробнее.

Замыкания в JavaScript

Замыкание (closure) в JavaScript — это функция, которая сохраняет доступ к переменным своей внешней (родительской) области видимости, даже после завершения работы этой области. Простыми словами, функция «запоминает» окружение, в котором она была создана, и использует переменные из этого окружения позже

В нашем примере:

(function(i) {
    var i = i;
    array.push(function() {
        return i + i;
    });
})(i);

Здесь создается замыкание: внутренняя функция сохраняет ссылку на переменную i, которая передается ей в качестве параметра. Таким образом, каждое выполнение внешнего цикла создает новое замыкание с уникальным значением i.

Немедленные функции (IIFE)

Немедленная функция (Immediately Invoked Function Expression, IIFE) — это функция, которая определяется и немедленно вызывается. Она часто используется для создания изолированной области видимости и предотвращения загрязнения глобальной области видимости.

В нашем коде:

(function(i) {
    ...
})(i);

Эта конструкция создает новую область видимости для каждой итерации цикла, предотвращая изменение значения i между итерациями.

Цикл while и уменьшение счетчика

Цикл while в JavaScript выполняется до тех пор, пока заданное условие истинно. В нашем случае:

while (i--) {
    ...
}

Важно отметить, что оператор -- уменьшает значение i после проверки условия. Это означает, что цикл начнется с i = 9 (так как начальное значение i = 10, но оно уменьшается перед первой итерацией).

Создание массива функций

Внутри цикла мы создаем и добавляем в массив функции:

array.push(function() {
    return i + i;
});

Эти функции сохраняют ссылку на переменную i благодаря механизму замыканий. Каждое замыкание хранит свое уникальное значение i, соответствующее моменту его создания.

Результат выполнения

Теперь давайте посмотрим, как это влияет на результат выполнения:

  1. Первая итерация: i = 9. Создается функция, возвращающая 9 + 9 = 18.
  2. Вторая итерация: i = 8. Создается функция, возвращающая 8 + 8 = 16.

Таким образом, при вызове первых двух функций массива:

[
  array[0](), // Возвращает 18
  array[1]() // Возвращает 16
]

Мы получаем результат [18, 16].

Итого

Понимание механизмов замыканий, немедленных функций и особенностей циклов в JavaScript позволяет эффективно управлять областью видимости и поведением функций в сложных конструкциях. Эта задача демонстрирует важность правильного управления состоянием переменных в циклических структурах и преимущества использования замыканий для сохранения уникальных значений.