Страницы

Поиск по вопросам

воскресенье, 12 января 2020 г.

Как работают замыкания (нюансы)? [дубликат]

#javascript #замыкания


        
             
                
                    
                        
                            На этот вопрос уже даны ответы здесь:
                            
                        
                    
                
                        
                            Как работают замыкания в JavaScript
                                
                                    (7 ответов)
                                
                        
                                Закрыт 3 года назад.
            
                    
Что такое замыкания мне понятно, но в ходе их исследования возникли нюансы:

Есть код:




Не могу осознать благодаря чему переменная numberOfCalls в функции createCounter
не обнуляется? Это фишка такая или этому есть разумное объяснение?
    


Ответы

Ответ 1



"Вы вызываете один раз функцию createCounter". "Замыкание" - создание объекта, содержащего экземпляры всех переменных из внешних областей видимости, используемых функцией. Вызовите функцию еще раз , а потом начинайте вызывать два результата в произвольном порядке: $(document).ready(function() { function createCounter() { var numberOfCalls = 0; return function() { return ++numberOfCalls; }; } function appendOutput(aText) { $("#output").append(aText + "
"); } $("#btnRun").click(function() { $("#output").html(""); var fn1 = createCounter(); var fn2 = createCounter(); appendOutput("fn1: " + fn1()); appendOutput("fn1: " + fn1()); appendOutput("fn1: " + fn1()); appendOutput("fn2: " + fn2()); appendOutput("fn2: " + fn2()); appendOutput("fn1: " + fn1()); }); });
output


Ответ 2



Её [переменную] один раз инициализировали, возвращённая функция находится вложеннее, и, так как переменная используется в функции, сборщик не убирает её. Полезное чтение почему так происходит.

Ответ 3



Особенность вложенных функций состоит в том, чтобы получать значения из нее. В данном случае, внутри одной функции создаётся другая и возвращается в качестве результата. В разработке интерфейсов это совершенно стандартный приём, функция затем может назначаться как обработчик действий посетителя. function createCounter() { // LexicalEnvironment = { numberOfCalls: undefined } var numberOfCalls = 0; // LexicalEnvironment = { numberOfCalls : 0 } return function() { // [[Scope]] -> LexicalEnvironment (**) return numberOfCalls++; }; } Как видно, мы получили независимый счётчик function(), каждый из которых, незаметным снаружи образом, сохраняет текущее количество вызовов. Если подробнее описать происходящее: 1) В строке (*) запускается createCounter(). При этом создаётся LexicalEnvironment для переменных текущего вызова. В функции есть одна переменная var numberOfCalls, которая станет свойством этого объекта. Она изначально инициализируется в undefined, затем в процессе выполнения получит значение 0. 2) В процессе выполнения createCounter() создаёт функцию в строке (**). При создании эта функция получает внутреннее свойство [[Scope]] со ссылкой на текущий LexicalEnvironment. 3) Далее вызов createCounter() завершается.

Комментариев нет:

Отправить комментарий