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

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

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 и даже оригинальный аргумент somearg.Но я не понимаю, почему они полезны.Какой смысл использовать «свободную» переменную local_value или, что еще более неизвестно мне, зачем вам использовать аргумент функции closureMaking в вашей функции закрытия?

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

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

Ответы [ 7 ]

6 голосов
/ 09 августа 2010

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

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; 
}());
4 голосов
/ 09 августа 2010

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

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

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

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

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

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

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

4 голосов
/ 09 августа 2010

Распространенным вводом является то, что в цикле 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 связан с автоматически выполняемыми анонимными функциями, вызываемыми в каждом приращении нашего цикла.Таким образом, состояние сохраняется, и мы получаем # право на предупреждение.

0 голосов
/ 09 августа 2010

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

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, который интенсивно использует замыкания.

0 голосов
/ 09 августа 2010

Если вы комениг из мира 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

0 голосов
/ 09 августа 2010

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

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

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

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

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 относительно некоторого корневого элемента;замыкание позволяет встроить это определение корневого элемента в саму функцию, а не зависеть от того, имеют ли вызывающие абоненты доступ к нему всякий раз, когда они хотят выполнить функцию.

0 голосов
/ 09 августа 2010

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

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

...