Замыкание и области видимости

Создать функцию, возвращающую массив функций, возвращающих свой индекс в массиве.

Объясните, как это сделать. Что-то совсем непонятна тема с замыканиями.


Ответы (1 шт):

Автор решения: Alexander Lonberg

Так как из массива могут вырезать данные, искать надо именно по ссылке на саму функцию - текущий индекс, а не индекс на момент создания.

Это не самое удачное задание, для объяснений с замыканиями, но комменты оставлю.

function arrayOfIndexesReturn(num = 10) {
  let arrayOfIndexes = []
  for (let i = 0; i < num; i++) {
    // Внутри цикла(и не только) можно определить временную переменную, ЖИВУЩУЮ РОВНО ОДНУ ИТЕРАЦИЮ.
    // let fun <- ВОТ ОНА

    // НО, если кто-то(А) получит на нее ссылку и этот А не собирается "самоуничтожиться",
    //   переменная будет доступна на протяжении всей жизни А и только для него.

    // Вот этим А и является функция - как видим fun используется аргументом в .indexOf(fun).
    // При этом никто не запрещает инициализировать нашу переменную fun этой самой функцией.
    let fun = () => ({ current: arrayOfIndexes.indexOf(fun), created: i})
    arrayOfIndexes.push(fun)

    // В этот самый момент, когда мы собирались покинуть итерацию и распрощаться 
    //   с временной переменной fun, и произошло это самое ЗАМЫКАНИЕ.
    // JavaScript сообразил: - Ведь кто-то воспользуется этой самой функцией, а значит будет
    //   нужна ссылка на fun. И сохранил лексическое окружение созданное на момент итерации.
  }
  return arrayOfIndexes
}

const arr = arrayOfIndexesReturn()
console.log(arr[5]())
arr.splice(0, 1)
// Реально это 7-ая добавленная функция, но после удаления,
// и благодаря замыканию, она найдет текущий индекс
console.log(arr[5]())

Лучше, конечно, разбирать ЗАМЫКАНИЯ на задачах типа счетчиков

const counter = ((n = 0) => {
  return () => ++n
})()

counter() // 1
counter() // 2
→ Ссылка