Подтвердить что ты не робот

Я знаю, что такое закрытие, но я до сих пор не понимаю, почему (или когда) вы будете использовать их

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

function closureMaker(somearg)
{
    var local_value = 7;
    function funcToReturn(arg1, arg2)
    {
        return local_value + somearg + arg1 + arg2;
    }
    return funcToReturn;
}
var myClosure = closureMaker(6);  //make the closure
myClosure(2, 3);                  //using it

Теперь у закрытия есть local_value и даже исходный arg, somearg. Но я не понимаю, почему они полезны. Какой смысл использовать "свободную" переменную local_value или даже более неизвестную мне, почему бы вы использовать аргумент функции closMaking в вашей функции закрытия?

Меня больше интересует, как это используется в javascript, много ли используется для запросов и объектов AJAX?

Я получил то, что. Мне нужно, почему.

4b9b3361

Ответ 1

Одним из наиболее практичных и широко распространенных способов использования закрытий является реализация частных или привилегированных членов, например:

function Test (param) {
  var secret = 3;
  function privateMethod() {
    //...
  }
  this.publicMember = param;
  this.privilegedMember = function () {
    return secret * param;
  };
}

var foo = new Test(10);
foo.privilegedMember(); // 30
foo.secret; // undefined

Шаблон модуля также является хорошим примером, который может использовать тот же принцип, например:

var myModule = (function () { 
  var obj = {}, privateVariable = 1; 

  function privateMethod() { 
    // ... 
  } 

  obj.publicProperty = 1; 
  obj.publicMethod = function () { 
    // private members available here... 
  }; 

  return obj; 
}());

Ответ 2

Обычный прогон - это то, что в цикле for вы хотите предупредить номер счетчика.

function addLinks () {
    for(var i = 0; i < 5; ++i) {
        var link = document.createElement('a');
        link.appendChild(document.createTextNode('Link ' + i));
        link.i = i;
        link.onclick = function() { alert( i ) };
        document.body.appendChild(link);
    }
}

addLinks();

Когда вы нажмете на эти ссылки, он предупредит 5, потому что цикл уже выполнен, а i равен 5. Мы не "сохранили" состояние i во время выполнения цикла for.

Мы можем сделать закрытие для "сохранения" этого состояния:

function addLinks () {
    for(var i = 0; i < 5; ++i) {
        var link = document.createElement('a');
        link.appendChild(document.createTextNode('Link ' + i));
        link.i = i;
        link.onclick = (function(i) { return function() {  alert(i ) } })(i);
        document.body.appendChild(link);
    }
}

addLinks();

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

Ответ 3

Пример, который вы смотрите, пытается показать вам, как работают замыкания. Я думаю о закрытии, как о небольших фрагментах кода, которые вы можете пройти. Оптимальным является то, что (свободные) переменные в замыкании связаны с текущей лексической областью. Вот почему local_value сохраняет значение 7, потому что это значение local_value было при создании замыкания.

Javascript реализует закрывает через анонимные функции * но имейте в виду, что технически это две отдельные концепции.

В контексте Javascript закрытие (реализовано как анонимные функции) очень полезно, когда вы хотите иметь дело с вещами, которые происходят асинхронно; хорошим примером является, как вы сказали, AJAX-запросы, где вы не можете предсказать, когда вы получите ответ с сервера. В этом случае у вас есть анонимная функция, называемая обратным вызовом, которую вы изначально определяете и передаете, когда вы совершаете вызов AJAX. Когда вызов успешно завершен, ваш обратный вызов вызывается для обработки результата. Закрытие приводит к созданию более чистого кода, так как вы можете встраивать в них поведение и логику. Это также помогает вам абстрагировать поведение наших и отдельных проблем.

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

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

Вот хорошая статья о закрытии в Javascript. Он длинный, но информативный:

* Как упоминалось в CMS, именованные функции будут вести себя как анонимные функции, потому что они будут иметь доступ к переменным, которые определены в той же лексической области (или что-то в цепочке). Это наиболее очевидно во внутренних функциях. Но если вы думаете об этом, то это происходит и для любой функции; у вас есть доступ к переменным, которые были определены в глобальной области (то есть глобальные переменные).

Ответ 4

Это, вероятно, не совсем то, что вы ищете, но есть прекрасная беседа о закрытии Java (как они должны/могут быть реализованы), а также некоторые примеры того, где вы хотели бы их использовать.

http://www.youtube.com/watch?v=0zVizaCOhME

Ответ 5

Закрытие - это простой способ сделать функции, зависящие от параметров. Или, другими словами, создать конкретный экземпляр семейства функций (читайте, если это не понятно) в зависимости от некоторого значения времени выполнения.

Javascript позволяет передавать функции в качестве первоклассных членов; например, вы можете передать функцию, которая определяет, как объединить два целых числа, обратившись к ней напрямую.

Однако, сделав еще один шаг, закрытие позволяет создать "настраиваемую" версию функции, точное поведение которой зависит от некоторой переменной времени выполнения (но которая в противном случае соответствует структуре).

Например, здесь функция, которая позволит curried добавить:

function getAddNFunction(n)
{
    function inner(operand)
    {
        return n + operand;
    }
    return inner;
}

Теперь, если вы вызываете getAddNFunction(7), вы получаете функцию, которая добавляет 7 к аргументу. Если вы вызываете getAddNFunction(42.5), вы получаете функцию, которая добавляет к аргументу 42.5.

Надеюсь, этот простой пример поясняет преимущества закрытия; они позволяют вставлять аргументы в функцию во время создания, а не передавать их во время выполнения (в конце концов, вызов getAddNFunction(9)(2) в точности совпадает с вызовом 9 + 2, за исключением того факта, что два аргумента могут поставляться в очень разное время).

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

Ответ 6

Если вы являетесь comnig из мира OO, закрытие позволяет вам создавать то, что является, по существу, частными переменными-членами и методами для ваших объектов:

function Constructor(...) {
  var privateVar = value;
  function privateFunc() {
  }
  this.publicFunc = function() {
  // public func has access to privateVar and privateFunc, but code outside Constructor does not
  }
}

Дуглас Крокфорд и доброта javascript

Ответ 7

В дополнение к закрытию выше помогает скрывать некоторые детали реализации.

var Counter = (function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  }   
})();

alert(Counter.value()); /* Alerts 0 */
Counter.increment();
Counter.increment();
alert(Counter.value()); /* Alerts 2 */
Counter.decrement();
alert(Counter.value()); /* Alerts 1 */

Еще одна хорошая статья

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