Замыкания


#1

Есть функция:

let c = 4;

function addX(x) {

  return function(n) {
    return n + x
  }

}

let addThree = addX(3);

let d = addThree(c);

console.log('example partial application', d); // example partial application 7

Подскажите, пожалуйста, в какой момент времени переменной «n» присваивается значение 4?

Насколько я понимаю, работает этот код так:

Функция addX(x) получает аргумент «3», далее передает это значение во внутреннюю функцию:

return function(n) {
  return n + x
}

А что возвращается отсюда? И почему возвращенный отсюда результат, записанный в:

let addThree

далее вызывается с аргументом addThree(с) (где «с» = 4) и все это равняется в итоге 7?

Как это работает?


#2

ну я уже бахнул пыва, так что будем вкуривать вместе =)

в момент, когда мы записываем

let addThree = addX(3); безымянная функция внутри addX перестает иметь тот вид, что имела изначально.
теперь это все вместе будет таким (абстрактно):

function addXnew(n) {
  return function(n) {
    return n + 3
  }
}

addThree = addXnew(n); - т.е. равно вызову функции, которая возвращает функцию
и дальше уже совсем просто.
присваиваем d вызов addThree(4) = addXnew(n)
т.е.:

function addXnew(4) {
  return function(4) {
    return 4 + 3
  }
}

в какой момент времени присваивается? в момент вызова addThree(c) =) т.е. в момент присвоения переменной d.
вот статейка, где более менее по нарастающей сложности рассказывают и подводят к замыканиям.

я пока еще с такой наркоманией не сталкивался, максимум коллбэки =)
если все еще остались вопросы, действительно ли так происходит, в безымянной функции сделайте n / x
соответственно с = 8
addX(4)
если получится 2, знач я все верно описал =)


#3

На самом деле нет. Из внутренней функции в данный момент ничего не возвращается, так как внутреннюю функцию никто не вызывал! Обратите внимание, что внутри функции addX(x) есть ОПИСАНИЕ внутренней функции, но ВЫЗОВА внутренней функции там нигде нет. Это важно. Пока мы не вызовем внутреннюю функцию, никакого возврата n+x не произойдёт.

Теперь разберёмся со строкой let addThree = addX(3). Она означает, что в переменную addThree сохранился результат вызова функции addX(x) с аргументом 3. Результатом вызова внешней функции является то, что она возвращает, в данном случает ОПИСАНИЕ внутренней функции. Еще раз: не результат работы внутренней функции (то есть n + x ), а её описание. Другими словами, в переменной addThree сохранится код: function(n) {return n + x}. Но не только это! Ещё в переменной addThree сохранится замыкание внутренней функции, в котором записано, что x = 3.
Таким образом, наша внутренняя функция перестала быть анонимной. Теперь она носит гордое имя addThree и имеет вид function(n) {return n+3}.
Ну а дальше, в строке let d = addThree© происходит вызов этой функции. 4 + 3 = 7 ,поэтому в переменную d сохранится значение 7.


#4

о, кайф, теперь и мне понятнее стало =)
все хотел написать что addX “какбы” перестает существовать, лишь оставляет после себя безымянную функцию, записываемую в addThree с переменной из замыкания, но чет под пывом не сообразил :joy:


#6

И вам спасибо


#7

Спасибо!