Javascript Закрытие - PullRequest
       0

Javascript Закрытие

9 голосов
/ 06 марта 2012

Я все еще путаюсь с концепцией замыкания в JavaScript.Я понял, что замыкание - это способность внутренней функции обращаться к переменной, созданной в ее материнской функции после возвращения материнской функции.Но я все еще не понимаю, зачем нам создавать внутреннюю функцию для защиты локальной переменной, если мы можем просто создать переменную внутри функции?

Ответы [ 8 ]

3 голосов
/ 06 марта 2012

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

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

function f() {
  var x = 0;
  return ++x; // x=1
} // Once the function has exited then "x" no longer exists.

Обратите внимание, чтоПеременная «x» является «активной» (живой, существующей) только тогда, когда управление программой переходит от начала функции «f ()» к ее концу.Но если мы заключим «x» во внутреннюю функцию, то x будет жить так же, как и внутренняя функция:

function g() {
  var x = 0;
  return function() {
    // Now "x" will live for as long as this function.
    return ++x;
  }
};
var counter = g();
counter(); // => 1
counter(); // => 2
counter(); // => 3

Теперь, когда мы вызываем «g ()», мы получаем другую функцию, а «x»активен до тех пор, пока на эту функцию ссылается переменная.

2 голосов
/ 09 марта 2012

Зачем использовать замыкание?

(function(){
    var current_page = 1;
    function previous_page() {
        current_page--;
        // update interface
    }
    function next_page() {
        current_page++;
        // update interface
    }
    // a bit of jQuery, ok?
    $('#previous').click(previous_page);
    $('#next').click(next_page);
})();

Посмотрите: у нас нет глобальных переменных, даже нет функций, определенных в глобальном пространстве ... пока что мы добавили поведение к событиям нажатия "#предыдущие кнопки "и" #next "для функции подкачки.Как бы вы сделали это без замыканий?Как бы вы это сделали, определяя переменную current_page внутри функций?

1 голос
/ 06 марта 2012

ИЗ ЗАКРЫТИЙ MDN

   why to use:

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

when not to use

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

Например, при создании нового объекта / класса методы обычно должны быть связаны с прототипом объекта, а нечем определено в конструкторе объекта.Причина в том, что всякий раз, когда вызывается конструктор, методы будут переназначаться (то есть для каждого создания объекта).

1 голос
/ 06 марта 2012

Вы только что ответили на свой вопрос, внутренняя функция защищает его переменную. jsFiddle

(function outer(){
    var foo = 'bar';
    function inner(){
        var foo = 'OMG NO!';
    }
    alert(foo);//alerts 'bar'
})()
1 голос
/ 06 марта 2012

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

Переменные «закрыты».

// constructor function
var myObject = function(message) {
    // private - scope is function level.  It's CLOSED OVER the the inner function (closure).
    //           not delcared as a JSON property so not visible externally
    var value = 0;
    // constructor returns JSON object with public methods
    // always constructed from the myObject var so it always hands back the same instance
    // of the public methods
    return {
        // nested functions have access to outer function variables.
        increment: function (inc) {
            value ++;
        },
        getValue: function() {
            return value;
        },
        // the inner function even has access to the outer function's args!
        getMessage: message
    }
};

Посмотрите на инструкцию возврата. Он возвращает открытый интерфейс - некоторые методы имеют доступ к закрытой переменной, потому что они находятся во внутренней функции. Для создания объектно-ориентированной инкапсуляции он использует переменную области действия JavaScripts.

После этого я могу это как:

var obj = myObject('Hello World');
obj.increment();
obj.increment();
console.log(obj.getValue());
console.log(obj.getMessage);
// should be undefined
console.log(obj.value);

Обратите внимание, что в этот момент потребитель не имеет доступа к защищенному / инкапсулированному значению или сообщению.

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

Код выше выводит:

2
Hello World
undefined

В качестве примечания я запускаю JavaScript с node.js

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

http://www.yuiblog.com/blog/2007/06/12/module-pattern/

0 голосов
/ 05 июля 2016

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

Мне нравится думать об этом как о машине. Когда вы ведете машину, происходит много сложных процессов, но обычному человеку не нужно знать об этом в среднем за день. Думайте обо всех этих сложностях как о «частных» переменных, скрытых замыканиями, которые значительно упрощают использование педали газа, тормоза, рычага переключения передач, рулевого колеса и т. Д.

Так, какова цель закрытия? Чтобы скрыть все сложные переменные и тому подобное, чтобы сделать скрипт более удобным для использования. Если вам нужно было беспокоиться о каждой переменной в скрипте каждый раз, когда вы хотите использовать какую-либо функцию в скрипте, это может быстро стать очень трудным. YAY ЗАКРЫТИЯ!

0 голосов
/ 06 марта 2012

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

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

0 голосов
/ 06 марта 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...