Что такое «закрытие»? - PullRequest
       171

Что такое «закрытие»?

369 голосов
/ 31 августа 2008

Я задал вопрос о карринге, и были упомянуты закрытия. Что такое закрытие? Как это связано с карри?

Ответы [ 19 ]

2 голосов
/ 07 сентября 2013

Короче говоря, указатель функции - это просто указатель на местоположение в базе программного кода (например, счетчик программы). Принимая во внимание, что Закрытие = указатель на функцию + кадр стека .

.

1 голос
/ 18 апреля 2019

Закрытие - это функция в JavaScript, где функция имеет доступ к своим собственным переменным области действия, доступ к внешним переменным функции и доступ к глобальным переменным.

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

Внутренняя функция может обращаться к переменным, определенным в ее собственной области видимости, области видимости внешней функции и глобальной области видимости. А внешняя функция может обращаться к переменной, определенной в ее собственной области видимости и глобальной области видимости.

******************
Example of Closure
******************

var globalValue = 5;

function functOuter() 
{
    var outerFunctionValue = 10;

    //Inner function has access to the outer function value
    //and the global variables
    function functInner() 
    {
        var innerFunctionValue = 5;
        alert(globalValue+outerFunctionValue + innerFunctionValue);
    }
    functInner();
}
functOuter();

Вывод будет равен 20, который представляет собой сумму его внутренней функции, собственной переменной, внешней переменной функции и значения глобальной переменной.

0 голосов
/ 15 декабря 2018

Пожалуйста, посмотрите код ниже, чтобы понять закрытие более подробно:

        for(var i=0; i< 5; i++){            
            setTimeout(function(){
                console.log(i);
            }, 1000);                        
        }

Вот что будет выводиться? 0,1,2,3,4 не то, что будет 5,5,5,5,5 из-за закрытия

Так как это решит? Ответ ниже:

       for(var i=0; i< 5; i++){
           (function(j){     //using IIFE           
                setTimeout(function(){
                               console.log(j);
                           },1000);
            })(i);          
        }

Позвольте мне просто объяснить, когда созданная функция ничего не происходит, пока она не вызовет цикл for в 1-м коде, вызываемый 5 раз, но не вызывается сразу, поэтому, когда она вызывается, т. Е. Через 1 секунду, и это также асинхронно, так что до этого цикл завершается сохранить значение 5 в переменной i и, наконец, выполнить setTimeout функцию пять раз и вывести 5,5,5,5,5

Вот как это решить, используя IIFE, т.е. выражение функции немедленного вызова

       (function(j){  //i is passed here           
            setTimeout(function(){
                           console.log(j);
                       },1000);
        })(i);  //look here it called immediate that is store i=0 for 1st loop, i=1 for 2nd loop, and so on and print 0,1,2,3,4

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

  • Существует еще одно решение, позволяющее решить эту проблему с помощью let (функция ES6), но под капотом работает вышеуказанная функция

     for(let i=0; i< 5; i++){           
         setTimeout(function(){
                        console.log(i);
                    },1000);                        
     }
    
    Output: 0,1,2,3,4
    

=> Дополнительные пояснения:

В памяти, когда для выполнения цикла выполняется картинка, как показано ниже:

Петля 1)

     setTimeout(function(){
                    console.log(i);
                },1000);  

Петля 2)

     setTimeout(function(){
                    console.log(i);
                },1000); 

Петля 3)

     setTimeout(function(){
                    console.log(i);
                },1000); 

Петля 4)

     setTimeout(function(){
                    console.log(i);
                },1000); 

Петля 5)

     setTimeout(function(){
                    console.log(i);
                },1000);  

Здесь я не выполняется, а затем после полного цикла, я сохраняю значение 5 в памяти, но его область видимости всегда видна в дочерней функции, поэтому, когда функция выполняется внутри setTimeout из пяти раз, она печатает 5,5,5,5,5

, чтобы решить эту проблему, используйте IIFE, как описано выше.

0 голосов
/ 03 августа 2017

Затворы Всякий раз, когда у нас есть функция, определенная внутри другой функции, внутренняя функция имеет доступ к объявленным переменным во внешней функции. Замыкания лучше всего объяснить на примерах. В листинге 2-18 видно, что внутренняя функция имеет доступ к переменной (variableInOuterFunction) из внешняя сфера. Переменные во внешней функции были закрыты (или связаны) с внутренней функцией. Отсюда и термин закрытие. Само понятие достаточно просто и довольно интуитивно понятно.

Listing 2-18:
    function outerFunction(arg) {
     var variableInOuterFunction = arg;

     function bar() {
             console.log(variableInOuterFunction); // Access a variable from the outer scope
     }
     // Call the local function to demonstrate that it has access to arg
     bar(); 
    }
    outerFunction('hello closure!'); // logs hello closure!

источник: http://index -of.es / Varios / Basarat% 20Ali% 20Syed% 20 (авторизация) - начало% 20Node.js-Apress% 20 (2014) .pdf

0 голосов
/ 12 мая 2011

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

local old_dofile = dofile

function dofile( filename )
  if filename == nil then
    error( 'Can not use default of stdin.' )
  end

  old_dofile( filename )
end

Значение old_dofile исчезает, когда этот блок кода завершает свою область действия (потому что оно локальное), однако значение было заключено в замыкание, поэтому новая переопределенная функция dofile МОЖЕТ получить к нему доступ, точнее, копия, сохраненная вместе с функция как «повышенное значение».

0 голосов
/ 04 мая 2019

Curry: позволяет частично оценить функцию, передав только подмножество ее аргументов. Учтите это:

function multiply (x, y) {
  return x * y;
}

const double = multiply.bind(null, 2);

const eight = double(4);

eight == 8;

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

function apple(x){
   function google(y,z) {
    console.log(x*y);
   }
   google(7,2);
}

apple(3);

// the answer here will be 21
0 голосов
/ 02 апреля 2016

Если вы из мира Java, вы можете сравнить замыкание с функцией-членом класса. Посмотрите на этот пример

var f=function(){
  var a=7;
  var g=function(){
    return a;
  }
  return g;
}

Функция g является закрытием: g закрывает a in. Таким образом, g можно сравнить с функцией-членом, a можно сравнить с полем класса, а функцию f с классом.

0 голосов
/ 29 мая 2019

Закрытие очень просто. Мы можем рассмотреть это следующим образом: Закрытие = функция + его лексическое окружение

Рассмотрим следующую функцию:

function init() {
    var name = “Mozilla”;
}

Каким будет закрытие в вышеуказанном случае? Функция init () и переменные в ее лексической среде, т. Е. Имя. Закрытие = init () + имя

Рассмотрим другую функцию:

function init() {
    var name = “Mozilla”;
    function displayName(){
        alert(name);
}
displayName();
}

Какими будут здесь закрытия? Внутренняя функция может обращаться к переменным внешней функции. displayName () может получить доступ к имени переменной, объявленной в родительской функции init (). Однако те же локальные переменные в displayName () будут использоваться, если они существуют.

Закрытие 1: функция инициализации + (переменная имени + функция displayName ()) -> лексическая область действия

Закрытие 2: Функция displayName + (переменная имени) -> лексическая область действия

0 голосов
/ 31 декабря 2015

С Lua.org :

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

...